144 Stimmen

Android Bild-Caching

Wie kann ich Bilder in den Cache stellen, nachdem sie aus dem Internet heruntergeladen wurden?

178voto

edrowland Punkte 1789

Und nun 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, der gemeinsam mit dem Browser genutzt wird.

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

66voto

Joe Punkte 793

Bezüglich der eleganten connection.setUseCaches Lösung oben: Leider wird es nicht ohne zusätzlichen Aufwand funktionieren. Sie müssen ein ResponseCache mit ResponseCache.setDefault . Ansonsten, HttpURLConnection ignoriert stillschweigend die setUseCaches(true) etwas.

Siehe die Kommentare am Anfang der Seite FileResponseCache.java für Details:

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

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

28voto

Samuh Punkte 35993

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, sollten Sie sie um eine java.lang.ref.SoftReference insbesondere wenn ihre Anzahl groß ist (so dass sie in Krisenzeiten in den Müll wandern). Dies könnte allerdings ein Reload zur Folge haben.

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

Um sie auf die SD-Karte zu schreiben, ist kein Reload erforderlich, sondern nur eine Benutzererlaubnis.

27voto

Zubair Ahmed Punkte 2807

Utilice LruCache um Bilder effizient zwischenzuspeichern. Sie können lesen über LruCache von Android-Entwickler-Website

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

SCHRITT 1: make Class Named 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:

eine weitere Klasse mit dem Namen DownloadImageTask erstellen, die verwendet wird, wenn die Bitmap nicht im Cache vorhanden ist, wird sie 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: Nutzung von Ihrem Activity o Adapter

Nota: Wenn Sie ein Bild aus einer Url laden möchten, die von Activity Klasse. Verwenden Sie den zweiten Konstruktor von DownloadImageTask , aber wenn Sie ein Bild aus Adapter verwenden Sie den ersten Constructor von DownloadImageTask (zum Beispiel haben Sie ein Bild in ListView und Sie setzen das Bild von 'Adapter')

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

Nota:

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

Ich bin nie gut darin, Dinge zu erklären, aber ich hoffe, dass dies den Anfängern helfen wird, wie man den Cache mit LruCache und seine Verwendung :)

EDIT :

Heutzutage gibt es sehr berühmte Bibliotheken, die als Picasso y Glide die zum sehr effizienten Laden von Bildern in einer Android-App verwendet werden kann. Probieren Sie diese sehr einfache und nützliche Bibliothek aus Picasso für Android y Gleiten für Android . Sie brauchen sich nicht um Cache-Bilder zu kümmern.

Picasso ermöglicht müheloses in einer einzigen Code-Zeile!

Glide, genau wie Picasso, kann Quellen laden und anzeigen, während es gleichzeitig für die Zwischenspeicherung und einen geringen Speicherbedarf sorgt. bei Bildmanipulationen. Es wurde verwendet von offiziellen Google-Apps verwendet (wie die App für die Google I/O 2015) und ist genauso beliebt wie wie Picasso. In dieser Serie werden wir die Unterschiede und Vorteile von Glide gegenüber Picasso.

Sie können auch den Blog besuchen für Unterschied zwischen Glide und Picasso

18voto

Ljdawson Punkte 11907

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, die Interneterlaubnis zu Ihrem Manifest hinzuzufügen:

<uses-permission android:name="android.permission.INTERNET" />

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X