Zwischenspeichern von Android-Bildern

Lesezeit: 11 Minuten

Zwischenspeichern von Android Bildern
D-Mann

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

Zwischenspeichern von Android Bildern
edrowland

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;
} 

Stellt sowohl Arbeitsspeicher als auch Flash-ROM-Cache bereit, die mit dem Browser geteilt werden.

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

  • Wow, das war eine unglaublich elegante Art, dies zu tun, vielen Dank. Es ist in keiner Weise langsamer als mein eigener einfacher Cache-Manager, und jetzt muss ich mich nicht mehr um einen SD-Kartenordner kümmern.

    – Kevin Lesen

    16. Oktober 2010 um 20:44 Uhr

  • connection.getContent() gibt mir immer einen InputStream zurück, was mache ich falsch?

    – Tyler Collier

    7. Juli 2011 um 18:36 Uhr

  • Wenn ich jetzt auch ein Ablaufdatum für den Inhalt des Caches festlegen könnte, wäre mein Leben so viel einfacher 🙂

    – Janusz

    12. Juli 2011 um 7:11 Uhr

  • @Scienceprodigy keine Ahnung, was dieser BitmapLoader ist, ist sicherlich nicht in irgendeiner Standard-Android-Bibliothek, die ich kenne, aber es hat mich zumindest in die richtige Richtung geführt. Bitmap response = BitmapFactory.decodeStream((InputStream)connection.getContent());

    – Stefan Fuhry

    30. September 2011 um 18:07 Uhr


  • Sehen Sie sich unbedingt Joes Antwort unten zu den zusätzlichen Schritten an, die Sie unternehmen müssen, damit der Cache funktioniert

    – Keith

    1. November 2011 um 18:22 Uhr

1646008991 786 Zwischenspeichern von Android Bildern
Jo

Apropos elegant connection.setUseCaches Lösung oben: Ohne zusätzlichen Aufwand geht es leider nicht. Sie müssen eine installieren ResponseCache verwenden ResponseCache.setDefault. Andernfalls, HttpURLConnection wird das stillschweigend ignorieren setUseCaches(true) bisschen.

Siehe die Kommentare oben FileResponseCache.java für Details:

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.)

  • Hier ist das Datei

    – Telemako

    22. November 2012 um 16:02 Uhr


  • Wenn Sie eine verwenden HttpResponseCachevielleicht finden Sie die HttpResponseCache.getHitCount() Rückgabe von 0. Ich bin mir nicht sicher, aber ich denke, das liegt daran, dass der von Ihnen angeforderte Webserver in diesem Fall keine Caching-Header verwendet. Damit das Caching trotzdem funktioniert, verwenden Sie connection.addRequestProperty("Cache-Control", "max-stale=" + MAX_STALE_CACHE);.

    – Almer

    18. März 2013 um 14:51 Uhr

  • Der Link zur Google-Codesuche ist (wieder?) tot, bitte aktualisieren Sie den Link.

    – Felix D.

    8. Dezember 2016 um 15:26 Uhr

  • 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 bei der Verwendung aufhängen .getContent() -Methode, da 304-Antworten gemäß RFC-Standard keinen zugeordneten Antworttext haben.

    – TheRealChx101

    16. Juli 2019 um 16:58 Uhr

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

Wenn Sie sie mit dem ersten Ansatz im Anwendungsbereich speichern, möchten Sie sie möglicherweise um a wickeln java.lang.ref.SoftReference insbesondere wenn ihre Anzahl groß ist (damit sie während der Krise von Müll abgeholt werden). Dies könnte jedoch ein Reload zur Folge haben.

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

das Schreiben auf die SD-Karte erfordert kein Neuladen; nur eine Benutzerberechtigung.

  • Wie können wir ein Bild auf die SD-Karte oder den Telefonspeicher schreiben?

    – D-Mann

    22. Dezember 2009 um 11:05 Uhr

  • So speichern Sie Bilder auf einer SD-Karte: Sie können entweder die vom Remote-Server gelesenen Bildströme mit normalen Datei-E/A-Vorgängen in den Speicher schreiben oder, wenn Sie Ihre Bilder in Bitmap-Objekte konvertiert haben, die Methode Bitmap.compress() verwenden.

    – Samuh

    22. Dezember 2009 um 11:39 Uhr

  • @d-man Ich würde vorschlagen, zuerst die auf die Festplatte zu schreiben und dann eine zu erhalten Uri Pfadreferenz, an die Sie übergeben können ImageView und andere benutzerdefinierte Ansichten. Denn jedes Mal, wenn Sie compress, du verlierst Qualität. Dies gilt natürlich nur für verlustbehaftete Algorithmen. Diese Methode würde es Ihnen auch ermöglichen, sogar einen Hash der Datei zu speichern und ihn zu verwenden, wenn Sie die Datei das nächste Mal vom Server anfordern If-None-Match und ETag Kopfzeilen.

    – TheRealChx101

    16. Juli 2019 um 17:03 Uhr

  • @ TheRealChx101 könnten Sie bitte helfen zu verstehen, was Sie meinen Wenn Sie die Datei das nächste Mal vom Server über If-None-Match- und ETag-Header anfordernIch suche im Grunde nach einem Lösungsansatz, bei dem das Bild bleiben sollte, um den lokalen Cache für einen definierten Zeitraum zu verwenden, ODER wenn dies nicht erreicht werden kann, sollte es bei jeder Änderung des Inhalts für die URL in der Anwendung mit dem neuesten widergespiegelt und zwischengespeichert werden.

    – Code

    24. August 2019 um 1:06 Uhr

  • @CoDe Besuchen Sie jetzt diesen Link, android.jlelse.eu/…

    – TheRealChx101

    24. August 2019 um 22:19 Uhr

Zwischenspeichern von Android Bildern
Zubair Ahmed

Verwenden LruCache um Bilder effizient zwischenzuspeichern. Sie können darüber lesen LruCache von Android-Entwicklerseite

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

SCHRITT 1:
Klasse benannt machen ImagesCache. Ich habe verwendet Singleton 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 namens DownloadImageTask, die verwendet wird, wenn Bitmap nicht im Cache verfügbar ist, und sie von hier heruntergeladen wird:

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: Nutzung von Ihrem Activity oder Adapter

Notiz: Wenn Sie ein Bild von einer URL laden möchten Activity Klasse. Verwenden Sie den zweiten Konstruktor von DownloadImageTaskaber wenn Sie ein Bild von anzeigen möchten Adapter Verwenden Sie den ersten Konstruktor von DownloadImageTask (Beispiel: Sie haben ein Bild in ListView und Sie stellen das Bild von ‘Adapter’ ein)

NUTZUNG VON AKTIVITÄTEN:

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);
}

Notiz:

cache.initializeCache() Sie können diese Anweisung in der allerersten Aktivität Ihrer Bewerbung verwenden. Sobald Sie den Cache initialisiert haben, müssen Sie ihn nicht jedes Mal initialisieren, wenn Sie ihn verwenden ImagesCache Beispiel.

Ich bin nie gut darin, Dinge zu erklären, aber ich hoffe, dass dies den Anfängern hilft, wie man cachet LruCache und seine Verwendung 🙂

BEARBEITEN:

Heutzutage gibt es sehr berühmte Bibliotheken, die als bekannt sind Picasso und Glide die verwendet werden können, um Bilder sehr effizient in die Android-App zu laden. Probieren Sie diese sehr einfache und nützliche Bibliothek aus 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 – oft in einer Codezeile!

Glide kann, genau wie Picasso, Bilder aus vielen Quellen laden und anzeigen, während es sich auch um das Caching kümmert und eine geringe Speicherauslastung bei Bildmanipulationen beibehält. 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 für besuchen Unterschied zwischen Glide und Picasso

Um ein Bild herunterzuladen und auf der Speicherkarte zu speichern, können Sie wie folgt vorgehen.

//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" />

  • Warum dekodieren Sie das JPEG und kodieren es dann neu? Es ist besser, die URL in ein Byte-Array herunterzuladen und dann dieses Byte-Array zu verwenden, um Ihre Bitmap zu erstellen und in eine Datei zu schreiben. Jedes Mal, wenn Sie ein JPEG dekodieren und neu kodieren, verschlechtert sich die Bildqualität.

    – CommonsWare

    22. Dezember 2009 um 16:33 Uhr

  • Fairer Punkt, war mehr für Geschwindigkeit als alles andere. Obwohl, wenn als Byte-Array gespeichert und die Quelldatei kein JPEG wäre, müsste die Datei nicht trotzdem konvertiert werden? “decodeByteArray” aus dem SDK gibt “Die dekodierte Bitmap oder null zurück, wenn die Bilddaten nicht dekodiert werden konnten”, also denke ich, dass die Bilddaten immer dekodiert werden, also müsste dies nicht erneut kodiert werden?

    – Ljdawson

    22. Dezember 2009 um 17:32 Uhr

  • Apropos Effizienz, wäre es nicht effizient, wenn wir statt FileOutputStream BufferedOutputStream übergeben würden?

    – Samuh

    23. Dezember 2009 um 4:18 Uhr

  • Ich schlage nicht vor, 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 IMO bevorzugt

    – James

    28. Januar 2011 um 20:52 Uhr

  • Mit einem APK-Limit von jetzt 50 MB ist das Caching auf der SD-Karte möglicherweise die einzige Möglichkeit für Entwickler.

    – Ljdawson

    28. Januar 2011 um 21:24 Uhr

1646008992 604 Zwischenspeichern von Android Bildern
Kunu

Ich würde in Betracht ziehen, den Bildcache von droidfu zu verwenden. Es implementiert sowohl einen In-Memory- als auch einen festplattenbasierten Image-Cache. Sie erhalten auch eine WebImageView, die die Vorteile der 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/

  • Warum dekodieren Sie das JPEG und kodieren es dann neu? Es ist besser, die URL in ein Byte-Array herunterzuladen und dann dieses Byte-Array zu verwenden, um Ihre Bitmap zu erstellen und in eine Datei zu schreiben. Jedes Mal, wenn Sie ein JPEG dekodieren und neu kodieren, verschlechtert sich die Bildqualität.

    – CommonsWare

    22. Dezember 2009 um 16:33 Uhr

  • Fairer Punkt, war mehr für Geschwindigkeit als alles andere. Obwohl, wenn als Byte-Array gespeichert und die Quelldatei kein JPEG wäre, müsste die Datei nicht trotzdem konvertiert werden? “decodeByteArray” aus dem SDK gibt “Die dekodierte Bitmap oder null zurück, wenn die Bilddaten nicht dekodiert werden konnten”, also denke ich, dass die Bilddaten immer dekodiert werden, also müsste dies nicht erneut kodiert werden?

    – Ljdawson

    22. Dezember 2009 um 17:32 Uhr

  • Apropos Effizienz, wäre es nicht effizient, wenn wir statt FileOutputStream BufferedOutputStream übergeben würden?

    – Samuh

    23. Dezember 2009 um 4:18 Uhr

  • Ich schlage nicht vor, 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 IMO bevorzugt

    – James

    28. Januar 2011 um 20:52 Uhr

  • Mit einem APK-Limit von jetzt 50 MB ist das Caching auf der SD-Karte möglicherweise die einzige Möglichkeit für Entwickler.

    – Ljdawson

    28. Januar 2011 um 21:24 Uhr

1646008992 537 Zwischenspeichern von Android Bildern
2 TassenTech

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

  • Einverstanden – SoftReferences werden auf den von mir getesteten Geräten sehr schnell zurückgefordert

    – essilber

    29. November 2011 um 7:04 Uhr

  • Google hat selbst bestätigt, dass Dalviks GC beim Sammeln sehr aggressiv ist SoftReferenceS. Sie empfehlen die Verwendung ihrer LruCache stattdessen.

    – kaka

    4. September 2012 um 21:08 Uhr

882260cookie-checkZwischenspeichern von Android-Bildern

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy