Android-Bild-Caching

141

Wie kann ich Bilder zwischenspeichern, nachdem sie aus dem Internet heruntergeladen wurden?

D-Mann
quelle

Antworten:

177

Und jetzt die Pointe: Verwenden Sie den System-Cache.

URL url = new URL(strUrl);
URLConnection connection = url.openConnection();
connection.setUseCaches(true);
Object response = connection.getContent();
if (response instanceof Bitmap) {
  Bitmap bitmap = (Bitmap)response;
} 

Bietet sowohl Speicher als auch Flash-ROM-Cache, die für den Browser freigegeben sind.

grr. Ich wünschte, jemand hätte mir das gesagt, bevor ich meinen eigenen Cache-Manager schrieb.

Edrowland
quelle
1
Wow, das war eine unglaublich elegante Art, vielen Dank. Es ist keineswegs langsamer als mein einfacher Cache-Manager, und jetzt muss ich mich nicht mehr um einen SD-Kartenordner kümmern.
Kevin Read
11
connection.getContent()Gibt immer einen InputStream für mich zurück. Was mache ich falsch?
Tyler Collier
3
Wenn ich jetzt auch ein Ablaufdatum für den Inhalt des Caches festlegen könnte, wäre mein Leben so viel einfacher :)
Janusz
11
@Scienceprodigy keine Ahnung, was dieser BitmapLoader ist, sicherlich nicht in einer mir bekannten Standard-Android-Bibliothek, aber es hat mich zumindest in die richtige Richtung geführt. Bitmap response = BitmapFactory.decodeStream((InputStream)connection.getContent());
Stephen Fuhry
6
Lesen Sie unbedingt Joes Antwort unten über die zusätzlichen Schritte, die Sie ausführen müssen, um den Cache zum Laufen zu bringen
Keith
65

In Bezug auf die elegante connection.setUseCachesLösung oben: Leider funktioniert es nicht ohne zusätzlichen Aufwand. Sie müssen eine ResponseCacheusing installieren ResponseCache.setDefault. Andernfalls HttpURLConnectionwird das setUseCaches(true)Bit stillschweigend ignoriert .

Weitere FileResponseCache.javaInformationen finden Sie in den Kommentaren oben auf:

http://libs-for-android.googlecode.com/svn/reference/com/google/android/filecache/FileResponseCache.html

(Ich würde dies in einem Kommentar posten, aber ich habe anscheinend nicht genug SO-Karma.)

Joe
quelle
Hier ist die Datei
Telémako
2
Wenn Sie eine verwenden HttpResponseCache, finden Sie möglicherweise die HttpResponseCache.getHitCount()Rückgabe 0. Ich bin nicht sicher, aber ich denke, das liegt daran, dass der von Ihnen angeforderte Webserver in diesem Fall keine Caching-Header verwendet. Verwenden Sie, um das Caching trotzdem zum Laufen zu bringen connection.addRequestProperty("Cache-Control", "max-stale=" + MAX_STALE_CACHE);.
Almer
1
Google Codesearch Link ist tot (wieder?), Bitte aktualisieren Sie den Link.
Felix D.
Ich bin mir auch nicht sicher, ob dieses Verhalten jetzt behoben ist. Aus irgendeinem Grund würde die Rückgabe von 304 vom Server HUC hängen, wenn die .getContent()Methode verwendet wird, da 304 Antworten nach RFC-Standard kein Antworttext zugeordnet ist.
TheRealChx101
27

Konvertieren Sie sie in Bitmaps und speichern Sie sie entweder in einer Sammlung (HashMap, Liste usw.) oder Sie können sie auf die SD-Karte schreiben.

Wenn Sie sie mit dem ersten Ansatz im Anwendungsbereich speichern, möchten Sie sie möglicherweise um eine java.lang.ref.SoftReference wickeln, insbesondere wenn ihre Anzahl groß ist (damit sie während der Krise als Müll gesammelt werden). Dies könnte jedoch zu einem Neuladen führen.

HashMap<String,SoftReference<Bitmap>> imageCache =
        new HashMap<String,SoftReference<Bitmap>>();

Für das Schreiben auf eine SD-Karte ist kein erneutes Laden erforderlich. nur eine Benutzerberechtigung.

Samuh
quelle
Wie können wir Bilder auf SD- oder Telefonspeicher schreiben?
D-Man
So speichern Sie Bilder auf einer SD-Karte: Sie können die vom Remote-Server gelesenen Bildströme entweder mit normalen Datei-E / A-Vorgängen in den Speicher übertragen oder die Bitmap.compress () -Methode verwenden, wenn Sie Ihre Bilder in Bitmap-Objekte konvertiert haben.
Samuh
@ d-man Ich würde vorschlagen, zuerst die Festplatte zu schreiben und dann eine UriPfadreferenz zu erhalten, an die Sie übergeben können, ImageViewsowie andere benutzerdefinierte Ansichten. Denn jedes Mal compressverlieren Sie an Qualität. Dies gilt natürlich nur für verlustbehaftete Algorithmen. Mit dieser Methode können Sie auch einen Hash der Datei speichern und beim nächsten Anfordern der Datei vom Server über If-None-Matchund in den ETagHeadern verwenden.
TheRealChx101
@ TheRealChx101 Könnten Sie bitte helfen, zu verstehen, was Sie meinen, wenn Sie das nächste Mal die Datei vom Server über If-None-Match- und ETag-Header anfordern ? Ich suche im Grunde nach einem Lösungsansatz, bei dem das Bild für die Definition des lokalen Cache verbleiben soll Zeitraum ODER Wenn dies nicht erreicht werden kann, sollte sich der Inhalt der URL in der Anwendung mit dem neuesten widerspiegeln und zwischengespeichert werden.
CoDe
@CoDe Besuchen Sie diesen Link für jetzt, android.jlelse.eu/…
TheRealChx101
27

Verwenden Sie LruCachediese Option, um Bilder effizient zwischenzuspeichern. Sie können über LruCachevon Android Developer Site lesen

Ich habe unten Lösung für das Herunterladen und Zwischenspeichern von Bildern in Android verwendet. Sie können die folgenden Schritte ausführen:

SCHRITT 1: Klasse benennen ImagesCache. Ich habe benutztSingleton object for this class

import android.graphics.Bitmap;
import android.support.v4.util.LruCache;

public class ImagesCache 
{
    private  LruCache<String, Bitmap> imagesWarehouse;

    private static ImagesCache cache;

    public static ImagesCache getInstance()
    {
        if(cache == null)
        {
            cache = new ImagesCache();
        }

        return cache;
    }

    public void initializeCache()
    {
        final int maxMemory = (int) (Runtime.getRuntime().maxMemory() /1024);

        final int cacheSize = maxMemory / 8;

        System.out.println("cache size = "+cacheSize);

        imagesWarehouse = new LruCache<String, Bitmap>(cacheSize)
                {
                    protected int sizeOf(String key, Bitmap value) 
                    {
                        // The cache size will be measured in kilobytes rather than number of items.

                        int bitmapByteCount = value.getRowBytes() * value.getHeight();

                        return bitmapByteCount / 1024;
                    }
                };
    }

    public void addImageToWarehouse(String key, Bitmap value)
    {       
        if(imagesWarehouse != null && imagesWarehouse.get(key) == null)
        {
            imagesWarehouse.put(key, value);
        }
    }

    public Bitmap getImageFromWarehouse(String key)
    {
        if(key != null)
        {
            return imagesWarehouse.get(key);
        }
        else
        {
            return null;
        }
    }

    public void removeImageFromWarehouse(String key)
    {
        imagesWarehouse.remove(key);
    }

    public void clearCache()
    {
        if(imagesWarehouse != null)
        {
            imagesWarehouse.evictAll();
        }       
    }

}

SCHRITT 2:

Erstellen Sie eine andere Klasse mit dem Namen DownloadImageTask, die verwendet wird, wenn die Bitmap nicht im Cache verfügbar ist. Sie wird von hier heruntergeladen:

public class DownloadImageTask extends AsyncTask<String, Void, Bitmap>
{   
    private int inSampleSize = 0;

    private String imageUrl;

    private BaseAdapter adapter;

    private ImagesCache cache;

    private int desiredWidth, desiredHeight;

    private Bitmap image = null;

    private ImageView ivImageView;

    public DownloadImageTask(BaseAdapter adapter, int desiredWidth, int desiredHeight) 
    {
        this.adapter = adapter;

        this.cache = ImagesCache.getInstance();

        this.desiredWidth = desiredWidth;

        this.desiredHeight = desiredHeight;
    }

    public DownloadImageTask(ImagesCache cache, ImageView ivImageView, int desireWidth, int desireHeight)
    {
        this.cache = cache;

        this.ivImageView = ivImageView;

        this.desiredHeight = desireHeight;

        this.desiredWidth = desireWidth;
    }

    @Override
    protected Bitmap doInBackground(String... params) 
    {
        imageUrl = params[0];

        return getImage(imageUrl);
    }

    @Override
    protected void onPostExecute(Bitmap result) 
    {
        super.onPostExecute(result);

        if(result != null)
        {
            cache.addImageToWarehouse(imageUrl, result);

            if(ivImageView != null)
            {
                ivImageView.setImageBitmap(result);
            }
            else if(adapter != null)
            {
                adapter.notifyDataSetChanged();
            }
        }
    }

    private Bitmap getImage(String imageUrl)
    {   
        if(cache.getImageFromWarehouse(imageUrl) == null)
        {
            BitmapFactory.Options options = new BitmapFactory.Options();

            options.inJustDecodeBounds = true;

            options.inSampleSize = inSampleSize;

            try
            {
                URL url = new URL(imageUrl);

                HttpURLConnection connection = (HttpURLConnection)url.openConnection();

                InputStream stream = connection.getInputStream();

                image = BitmapFactory.decodeStream(stream, null, options);

                int imageWidth = options.outWidth;

                int imageHeight = options.outHeight;

                if(imageWidth > desiredWidth || imageHeight > desiredHeight)
                {   
                    System.out.println("imageWidth:"+imageWidth+", imageHeight:"+imageHeight);

                    inSampleSize = inSampleSize + 2;

                    getImage(imageUrl);
                }
                else
                {   
                    options.inJustDecodeBounds = false;

                    connection = (HttpURLConnection)url.openConnection();

                    stream = connection.getInputStream();

                    image = BitmapFactory.decodeStream(stream, null, options);

                    return image;
                }
            }

            catch(Exception e)
            {
                Log.e("getImage", e.toString());
            }
        }

        return image;
    }

SCHRITT 3: Verwendung von Ihrem ActivityoderAdapter

Hinweis: Wenn Sie ein Bild von einer URL aus der ActivityKlasse laden möchten . Verwenden Sie den zweiten Konstruktor vonDownloadImageTask , aber wenn Sie ein Bild anzeigen möchten, Adapterverwenden Sie den ersten Konstruktor von DownloadImageTask(zum Beispiel haben Sie ein Bild in ListViewund setzen das Bild von 'Adapter').

NUTZUNG AUS DER AKTIVITÄT:

ImageView imv = (ImageView) findViewById(R.id.imageView);
ImagesCache cache = ImagesCache.getInstance();//Singleton instance handled in ImagesCache class.
cache.initializeCache();

String img = "your_image_url_here";

Bitmap bm = cache.getImageFromWarehouse(img);

if(bm != null)
{
  imv.setImageBitmap(bm);
}
else
{
  imv.setImageBitmap(null);

  DownloadImageTask imgTask = new DownloadImageTask(cache, imv, 300, 300);//Since you are using it from `Activity` call second Constructor.

  imgTask.execute(img);
}

VERWENDUNG VOM ADAPTER:

ImageView imv = (ImageView) rowView.findViewById(R.id.imageView);
ImagesCache cache = ImagesCache.getInstance();
cache.initializeCache();

String img = "your_image_url_here";

Bitmap bm = cache.getImageFromWarehouse(img);

if(bm != null)
{
  imv.setImageBitmap(bm);
}
else
{
  imv.setImageBitmap(null);

  DownloadImageTask imgTask = new DownloadImageTask(this, 300, 300);//Since you are using it from `Adapter` call first Constructor.

  imgTask.execute(img);
}

Hinweis:

cache.initializeCache()Sie können diese Anweisung in der allerersten Aktivität Ihrer Anwendung verwenden. Sobald Sie den Cache initialisiert haben, müssen Sie ihn nie mehr jedes Mal initialisieren, wenn Sie eine ImagesCacheInstanz verwenden.

Ich bin nie gut darin, Dinge zu erklären, aber ich hoffe, dies wird den Anfängern helfen, wie man die Verwendung LruCacheund ihre Verwendung zwischenspeichert :)

BEARBEITEN:

Heute gibt es sehr berühmte Bibliotheken, die als Picassound bekannt Glidesind, um Bilder sehr effizient in Android App zu laden. Probieren Sie diese sehr einfache und nützliche Bibliothek Picasso für Android und Glide für Android . Sie müssen sich keine Gedanken über Cache-Bilder machen.

Picasso ermöglicht das problemlose Laden von Bildern in Ihre Anwendung - häufig in einer Codezeile!

Glide kann genau wie Picasso Bilder aus vielen Quellen laden und anzeigen, während gleichzeitig das Zwischenspeichern und die geringe Auswirkung auf den Speicher bei Bildmanipulationen berücksichtigt werden. Es wurde von offiziellen Google Apps (wie der App für Google I / O 2015) verwendet und ist genauso beliebt wie Picasso. In dieser Serie werden wir die Unterschiede und Vorteile von Glide gegenüber Picasso untersuchen.

Sie können auch den Blog besuchen, um den Unterschied zwischen Glide und Picasso zu erfahren

Zubair Ahmed
quelle
3
Hervorragende Antwort und Erklärung! Ich denke, dies ist die beste Lösung, da es offline funktioniert und Android LruCache verwendet. Ich fand, dass die Lösung von edrowland im Flugzeugmodus nicht funktionierte, selbst wenn Joe hinzugefügt wurde, was mehr Integrationsaufwand erforderte. Übrigens scheint Android oder das Netzwerk eine erhebliche Menge an Caching zu bieten, selbst wenn Sie nichts extra tun. (Ein kleiner Fehler: Für die Beispielverwendung getImageFromWareHouse sollte das 'H' in Kleinbuchstaben übereinstimmen.) Danke!
Edwin Evans
1
tolle Erklärung :)
XtreemDeveloper
Könnten Sie die Methode getImage () erläutern, insbesondere, was sie mit der Bildgröße macht und wie es passiert? Ich verstehe zum Beispiel nicht, warum Sie die Funktion in sich selbst wieder aufrufen und wie sie funktioniert.
Greyshack
1
Upvote für das, if(cache == null)was mein Problem gelöst hat! :)
MR. Garcia
1
Siehe auch meine bearbeitete Antwort am Ende. Ich habe über berühmte Bibliotheken gesprochen, die heutzutage von den meisten Entwicklern verwendet werden. Probieren Sie diese Picasso: square.github.io/picasso und Glide: futurestud.io/blog/glide-getting-started
Zubair Ahmed
18

Um ein Bild herunterzuladen und auf der Speicherkarte zu speichern, können Sie dies folgendermaßen tun.

//First create a new URL object 
URL url = new URL("http://www.google.co.uk/logos/holiday09_2.gif")

//Next create a file, the example below will save to the SDCARD using JPEG format
File file = new File("/sdcard/example.jpg");

//Next create a Bitmap object and download the image to bitmap
Bitmap bitmap = BitmapFactory.decodeStream(url.openStream());

//Finally compress the bitmap, saving to the file previously created
bitmap.compress(CompressFormat.JPEG, 100, new FileOutputStream(file));

Vergessen Sie nicht, Ihrem Manifest die Internetberechtigung hinzuzufügen:

<uses-permission android:name="android.permission.INTERNET" />
Ljdawson
quelle
10
Warum dekodieren Sie das JPEG und kodieren es dann neu? Sie sollten die URL besser in ein Byte-Array herunterladen und dann mit diesem Byte-Array Ihre Bitmap erstellen und in eine Datei schreiben. Jedes Mal, wenn Sie ein JPEG dekodieren und neu codieren, wird die Bildqualität schlechter.
CommonsWare
2
Fairer Punkt, war mehr für Geschwindigkeit als alles andere. Wenn die Datei jedoch als Byte-Array gespeichert und die Quelldatei kein JPEG wäre, müsste sie nicht trotzdem konvertiert werden? "decodeByteArray" aus dem SDK gibt "Die dekodierte Bitmap oder null, wenn die Bilddaten nicht dekodiert werden konnten" zurück.
Ljdawson
Apropos Effizienz, wäre es nicht effizient, wenn wir anstelle von FileOutputStream BufferedOutputStream übergeben würden?
Samuh
1
Ich empfehle nicht, Bilder auf Ihrer SD-Karte zwischenzuspeichern. Sobald die Anwendung deinstalliert ist, werden die Bilder nicht entfernt, wodurch die SD-Karte mit nutzlosem Müll gefüllt wird. Das Speichern von Bildern im Cache-Verzeichnis der Anwendung wird bevorzugt. IMO
James
Mit einem APK-Limit von jetzt 50 MB ist das Zwischenspeichern auf der SD-Karte möglicherweise die einzige Möglichkeit für Entwickler.
Ljdawson
13

Ich würde in Betracht ziehen, den Bildcache von droidfu zu verwenden. Es implementiert sowohl einen speicherinternen als auch einen festplattenbasierten Image-Cache. Sie erhalten auch eine WebImageView, die die ImageCache-Bibliothek nutzt.

Hier ist die vollständige Beschreibung von droidfu und WebImageView: http://brainflush.wordpress.com/2009/11/23/droid-fu-part-2-webimageview-and-webgalleryadapter/

Silber
quelle
Er hat seinen Code seit 2010 überarbeitet. Hier ist der Root-Link: github.com/kaeppler/droid-fu
esilver
3
Dieser Link funktioniert immer noch nicht. Ich schrieb eine ähnliche Bibliothek namens Android-ImageManager github.com/felipecsl/Android-ImageManager
Felipe Lima
9

Ich habe SoftReferences ausprobiert, sie werden in Android zu aggressiv zurückgefordert, als dass ich der Meinung wäre, dass es keinen Sinn macht, sie zu verwenden

2cupsOfTech
quelle
2
Einverstanden - SoftReferences werden auf den von mir getesteten Geräten sehr schnell zurückgefordert
esilver
3
Google hat selbst bestätigt, dass Dalviks GC beim Sammeln von SoftReferences sehr aggressiv ist . Sie empfehlen stattdessen ihre LruCache.
Kaka
9

Wie Thunder Rabbit vorgeschlagen hat, ist ImageDownloader der beste für diesen Job. Ich fand auch eine leichte Variation der Klasse bei:

http://theandroidcoder.com/utilities/android-image-download-and-caching/

Der Hauptunterschied zwischen beiden besteht darin, dass der ImageDownloader das Android-Caching-System verwendet und der modifizierte den internen und externen Speicher als Caching verwendet, wobei die zwischengespeicherten Bilder unbegrenzt bleiben oder bis der Benutzer sie manuell entfernt. Der Autor erwähnt auch die Kompatibilität mit Android 2.1.

EZFrag
quelle
7

Dies ist ein guter Fang von Joe. Das obige Codebeispiel hat zwei Probleme - eines - das Antwortobjekt ist keine Instanz von Bitmap (wenn meine URL auf ein JPG verweist, wie z. B. http: \ website.com \ image.jpg, ist es ein

org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl $ LimitedInputStream).

Zweitens, wie Joe betont, findet kein Caching statt, ohne dass ein Antwortcache konfiguriert ist. Android-Entwickler müssen ihren eigenen Cache rollen. Hier ist ein Beispiel dafür, aber es werden nur im Speicher zwischengespeichert, was wirklich nicht die vollständige Lösung ist.

http://codebycoffee.com/2010/06/29/using-responsecache-in-an-android-app/

Die URLConnection-Caching-API wird hier beschrieben:

http://download.oracle.com/javase/6/docs/technotes/guides/net/http-cache.html

Ich denke immer noch, dass dies eine gute Lösung ist, um diesen Weg zu gehen - aber Sie müssen immer noch einen Cache schreiben. Klingt nach Spaß, aber ich würde lieber Features schreiben.

Peter Pascale
quelle
7

Es gibt einen speziellen Eintrag im offiziellen Trainingsbereich von Android dazu: http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

Der Abschnitt ist ziemlich neu, er war nicht da, als die Frage gestellt wurde.

Die vorgeschlagene Lösung ist die Verwendung eines LruCache. Diese Klasse wurde in Honeycomb eingeführt, ist aber auch in der Kompatibilitätsbibliothek enthalten.

Sie können einen LruCache initialisieren, indem Sie die maximale Anzahl oder die maximalen Einträge festlegen. Diese sortieren sie automatisch nach Ihren Wünschen und bereinigen weniger verwendete Einträge, wenn Sie das Limit überschreiten. Ansonsten wird es als normale Karte verwendet.

Der Beispielcode von der offiziellen Seite:

private LruCache mMemoryCache;

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    // Get memory class of this device, exceeding this amount will throw an
    // OutOfMemory exception.
    final int memClass = ((ActivityManager) context.getSystemService(
            Context.ACTIVITY_SERVICE)).getMemoryClass();

    // Use 1/8th of the available memory for this memory cache.
    final int cacheSize = 1024 * 1024 * memClass / 8;

    mMemoryCache = new LruCache(cacheSize) {
        @Override
        protected int sizeOf(String key, Bitmap bitmap) {
            // The cache size will be measured in bytes rather than number of items.
            return bitmap.getByteCount();
        }
    };
    ...
}

public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
    if (getBitmapFromMemCache(key) == null) {
        mMemoryCache.put(key, bitmap);
    }
}

public Bitmap getBitmapFromMemCache(String key) {
    return mMemoryCache.get(key);
}

Bisher waren SoftReferences eine gute Alternative, aber nicht mehr, zitiert von der offiziellen Seite:

Hinweis: In der Vergangenheit war eine beliebte Implementierung des Speichercaches ein SoftReference- oder WeakReference-Bitmap-Cache. Dies wird jedoch nicht empfohlen. Ab Android 2.3 (API Level 9) ist der Garbage Collector aggressiver beim Sammeln von weichen / schwachen Referenzen, was sie ziemlich ineffektiv macht. Darüber hinaus wurden vor Android 3.0 (API Level 11) die Sicherungsdaten einer Bitmap im nativen Speicher gespeichert, der nicht vorhersehbar freigegeben wurde. Dies kann dazu führen, dass eine Anwendung kurzzeitig ihre Speichergrenzen überschreitet und abstürzt.

Shalafi
quelle
3

Erwägen Sie die Verwendung der Universal Image Loader-Bibliothek von Sergey Tarasevich . Es kommt mit:

  • Laden von Multithread-Bildern. Hier können Sie die Größe des Thread-Pools definieren
  • Bild-Caching im Speicher, auf dem Dateisystem des Geräts und auf der SD-Karte.
  • Möglichkeit, den Ladevorgang und Ladeereignisse zu verfolgen

Universal Image Loader ermöglicht eine detaillierte Cache-Verwaltung für heruntergeladene Bilder mit den folgenden Cache-Konfigurationen:

  • UsingFreqLimitedMemoryCache: Die am seltensten verwendete Bitmap wird gelöscht, wenn die Cache-Größenbeschränkung überschritten wird.
  • LRULimitedMemoryCache: Das zuletzt verwendete Bitmap wird gelöscht, wenn die Cache-Größenbeschränkung überschritten wird.
  • FIFOLimitedMemoryCache: Die FIFO-Regel wird zum Löschen verwendet, wenn die Cache-Größenbeschränkung überschritten wird.
  • LargestLimitedMemoryCache: Das größte Bitmap wird gelöscht, wenn die Cache-Größenbeschränkung überschritten wird.
  • LimitedAgeMemoryCache: Das zwischengespeicherte Objekt wird gelöscht, wenn es Alter den definierten Wert überschreitet .
  • WeakMemoryCache: Ein Speichercache mit nur schwachen Verweisen auf Bitmaps.

Ein einfaches Anwendungsbeispiel:

ImageView imageView = groupView.findViewById(R.id.imageView);
String imageUrl = "http://site.com/image.png"; 

ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.init(ImageLoaderConfiguration.createDefault(context));
imageLoader.displayImage(imageUrl, imageView);

In diesem Beispiel wird die Standardeinstellung verwendet UsingFreqLimitedMemoryCache.

Gunnar Karlsson
quelle
Bei intensiver Verwendung verursacht der Universal Image Loader viele Speicherlecks. Ich vermute, dass dies passiert, weil es Singletons im Code verwendet (siehe 'getInstance ()' im Beispiel). Nachdem ich viele Bilder geladen und meinen Bildschirm ein paar Mal gedreht hatte, stürzte meine App aufgrund von OutOfMemoryErrors in UIL ständig ab. Es ist eine großartige Bibliothek, aber es ist eine bekannte Tatsache, dass Sie NIEMALS Singletons verwenden sollten, besonders nicht in Android ...
Geert Bellemans
1
BENUTZEN Sie Singletons, wenn Sie wissen wie! :)
Renetik
3

Was für mich tatsächlich funktionierte, war das Festlegen von ResponseCache für meine Hauptklasse:

try {
   File httpCacheDir = new File(getApplicationContext().getCacheDir(), "http");
   long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
   HttpResponseCache.install(httpCacheDir, httpCacheSize);
} catch (IOException e) { } 

und

connection.setUseCaches(true);

beim Herunterladen der Bitmap.

http://practicaldroid.blogspot.com/2013/01/utilizing-http-response-cache.html

ZamPrano
quelle
ist es möglich, lrucache in Verbindung mit httpresponsecache
iOSAndroidWindowsMobileAppsDev
1

Ich hatte seit einiger Zeit damit gerungen; Die Antworten mit SoftReferences würden ihre Daten zu schnell verlieren. Die Antworten, die darauf hindeuten, einen RequestCache zu instanziieren, waren zu chaotisch, und ich konnte nie ein vollständiges Beispiel finden.

Aber ImageDownloader.java funktioniert wunderbar für mich. Es wird eine HashMap verwendet, bis die Kapazität erreicht ist oder bis das Zeitlimit für die Bereinigung auftritt. Anschließend werden die Dinge in eine SoftReference verschoben, wodurch das Beste aus beiden Welten verwendet wird.

Donnerkaninchen
quelle
0

Noch später antworten, aber ich habe einen Android Image Manager geschrieben, der das Caching transparent (Speicher und Festplatte) handhabt. Der Code befindet sich auf Github https://github.com/felipecsl/Android-ImageManager

Felipe Lima
quelle
1
Ich habe dies zu einer ListView hinzugefügt und es scheint nicht sehr gut damit umzugehen. Gibt es eine spezielle Implementierung für ListViews?
0

Späte Antwort, aber ich dachte mir, ich sollte einen Link zu meiner Site hinzufügen, da ich ein Tutorial geschrieben habe, wie man einen Bildcache für Android erstellt: http://squarewolf.nl/2010/11/android-image-cache/ Update: the Die Seite wurde offline geschaltet, da die Quelle veraltet war. Ich schließe mich @elenasys in ihrem Rat an, Ignition zu verwenden .

Also an alle Leute, die über diese Frage stolpern und keine Lösung gefunden haben: Ich hoffe es gefällt euch! = D.

Thomas Vervest
quelle
0

Späte Antwort, aber ich denke, diese Bibliothek wird beim Zwischenspeichern von Bildern sehr hilfreich sein: https://github.com/crypticminds/ColdStorage .

Kommentieren Sie die ImageView einfach mit @LoadCache (R.id.id_of_my_image_view, "URL_to_downlaod_image_from"). Das Bild wird heruntergeladen und in die Bildansicht geladen. Sie können auch ein Platzhalterbild angeben und eine Animation laden.

Eine ausführliche Dokumentation der Anmerkung finden Sie hier: - https://github.com/crypticminds/ColdStorage/wiki/@LoadImage-annotation

Anurag Mandal
quelle