简体   繁体   中英

android bitmap caching

I would like to load images into a gallery view from a url?

I first make them a bitmap using this.

URL aURL = new URL(myRemoteImages[position]);
URLConnection conn = aURL.openConnection();
conn.setUseCaches(true);
conn.connect();
Object response = conn.getContent();
if (response instanceof Bitmap) {
    Bitmap bm = (Bitmap)response;

    InputStream is = conn.getInputStream();  
    /* Buffered is always good for a performance plus. */
    BufferedInputStream bis = new BufferedInputStream(is);
    /* Decode url-data to a bitmap. */

    bm = BitmapFactory.decodeStream(bis);
    bis.close();
    is.close();
    Log.v(imageUrl, "Retrieving image");

    /* Apply the Bitmap to the ImageView that will be returned. */
    i.setImageBitmap(bm);

How could I go about caching this bitmap? So when the user swipes the screen it doesn't reload over and over?

EDIT: I CALL getImage() to retreive the text url for each url.

i use both of these in a asyncTask. preExecute i call getImage() and doInBackground i set the gallery to the imageAdapter.

    private class MyTask extends AsyncTask<Void, Void, Void>{


                @Override
                protected Void doInBackground(Void... arg0) {try {
                            getImages();
                            Log.v("MyTask", "Image 1 retreived");
                            getImage2();
                            Log.v("MyTask", "Image 2 retreived");
                            getImage3();
                            Log.v("MyTask", "Image 3 retreived");
                            getImage4();
                            Log.v("MyTask", "Image 4 retreived");
                        } catch (IOException e) {
                            Log.e("MainMenu retreive image", "Image Retreival failed");
                            e.printStackTrace();
                        }
                    return null;
                }
                @Override

                protected void onPostExecute(Void notUsed){
                    ((Gallery) findViewById(R.id.gallery))
                          .setAdapter(new ImageAdapter(MainMenu.this));


                }

                        }

EDIT: getView() method

    public View getView(int position, View convertView, ViewGroup parent) {
                ImageView i = new ImageView(this.myContext);

                try {

                                URL aURL = new URL(myRemoteImages[position]);
                                URLConnection conn = aURL.openConnection();
                                conn.setUseCaches(true);
                                conn.connect();
                                Object response = conn.getContent();
                                if (response instanceof Bitmap) {
                                  Bitmap bm = (Bitmap)response;

You could store your images on the SDCard and on the launch of your application you need to initialize a component that keeps a HashMap<String,Bitmap> and initialize the map with the contents of a folder from the SDCard.

When you will need an image, you will first check if your HashMap contains the key of that image, let say myMap.contains(myFileName) and if it does you will fetch the image from the map, and if the image is not contained in your map you will need to download it, store id on the SDCard and put in in your map.

I'm not sure if this is the best solution, since if you have a large number of Bitmaps your application can run out of resources. Also I think storing Drawable instead of Bitmap will be less memory consuming.

EDIT:For your problem you need create a custom class that has a member Drawable and execute the URLConnection just when you first create your objects. After that in the getView() method you will just use myObj.getMyDrawable() to access the drawable for that specific object.

Since Android 4 it is possible to cache HTTP responses directly by the HttpUrlConnection . See this article: http://practicaldroid.blogspot.de/2013/01/utilizing-http-response-cache.html

Caching images on android is an level oriented task: Generally at Caching at two levels:

  1. Runtime Heap memory in a form key-value, where key being a identifier for image and value is object of bitmap. (Refer Here)

Most optimised Way for implementing it is LRUCache :

Which Basically maintains a LinkedList for recently accessed items where dump the items accessed at earliest due to memory limitation.

As this backing pixel data for a bitmap is stored in native memory. It is separate from the bitmap itself, which is stored in the Dalvik heap. The pixel data in native memory is not released in a predictable manner, potentially causing an application to briefly exceed its memory limits and crash.

private LruCache<String, Bitmap> mMemoryCache;

@Override
protected void onCreate(Bundle savedInstanceState) {

// Get max available VM memory, exceeding this amount will throw an
// OutOfMemory exception. Stored in kilobytes as LruCache takes an
// int in its constructor.
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);

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

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


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

}


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

}
  1. Disk Storage: As memory has limited storage with restricted lifecycle.

Memory Cache is good for speeding up in accessing recently viewed images but you can not rely on this for images available on this cache.

UIComponents with indefinite and large data set can easily fill up memory and resulting in loss of images.

Memory cache may get effected in situations like going in background while on call.

Disk Cache can help you to make images persist for longer.

One of it's Optimized way of using it is DiskLruCache

So When you look up for a bitmap in memory cache is result is nil you can try to access it from disk cache and incase you don't find it here too and then just load it from internet. For Implementation Refer here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM