Using LRU Image Caching According to HTTPResponseCache for Disk and Memory Caching

The original goal was to use both disk and memory. To do this, you need to implement LRU cache and DiskLruCache. However, since the HTTPResponse cache is using disk space, I decided to use the LRU cache and docon.setUseCaches(true);

The problem is, I really don't understand what's going on in the first place. For LRU and DiskLru cache, this is the algorithm:

enter image description here

i.e.

first check the memory cache for the image

if there is an image, return it and refresh the caches

else check disk cache

if the cache disk has an image, returns it and refreshes the caches

otherwise download the image from the internet, return it and refresh the caches

Now with the code below:

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;

    Context mContext;

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

        this.cache = ImagesCache.getInstance();

        this.desiredWidth = desiredWidth;

        this.desiredHeight = desiredHeight;
    }

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

        this.ivImageView = ivImageView;

        this.desiredHeight = desireHeight;

        this.desiredWidth = desireWidth;

        this.mContext = mContext;
    }

    @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();
            }
        }
                /*
        * IMPORTANT:
        * This enables your retrieval from the cache when working offline
        */
        /***
         * Force buffered operations to the filesystem. This ensures that responses
         * written to the cache will be available the next time the cache is opened,
         * even if this process is killed.
         */
        HttpResponseCache cache = HttpResponseCache.getInstalled();
        if(cache != null) {
            //the number of HTTP requests issued since this cache was created.
            Log.e("total num HTTP requests", String.valueOf(cache.getHitCount()));
            //the number of those requests that required network use.
            Log.e("num req network", String.valueOf(cache.getNetworkCount()));
            //the number of those requests whose responses were served by the cache.
            Log.e("num use cache", String.valueOf(cache.getHitCount()));
            //   If cache is present, flush it to the filesystem.
            //   Will be used when activity starts again.
            cache.flush();
            /***
             * Uninstalls the cache and releases any active resources. Stored contents
             * will remain on the filesystem.
             */
            //UNCOMMENTING THIS PRODUCES A java.lang.IllegalStateException: cache is closedtry {
              //  cache.close();
            //}
            //catch(IOException e){
              //  e.printStackTrace();
            //}
        }
    }

    private Bitmap getImage(String imageUrl) {
        if (cache.getImageFromWarehouse(imageUrl) == null) {
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            options.inSampleSize = inSampleSize;
            //installing the cache at application startup.
            try {
                HttpResponseCache cache = HttpResponseCache.getInstalled();
                if (cache == null) {
                    File httpCacheDir = new File(mContext.getCacheDir(), "http");
                    long HTTP_CACHE_SIZE_IN_BYTES = 1024 * 1024 * 1024; // 1GB
                    HttpResponseCache.install(httpCacheDir, HTTP_CACHE_SIZE_IN_BYTES);
                    //Log.e("Max DiskLRUCache Size", String.valueOf(DiskLruCache.getMaxSize());
                }
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            try {
                int readTimeout = 300000;
                int connectTimeout = 300000;
                URL url = new URL(imageUrl);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setUseCaches(true);
                connection.addRequestProperty("Cache-Control", "max-stale=" + maxStale);
                connection.setConnectTimeout(connectTimeout);
                connection.setReadTimeout(readTimeout);
                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();
                    connection.setUseCaches(true);
                    connection.addRequestProperty("Cache-Control", "only-if-cached");
                    connection.setConnectTimeout(connectTimeout);
                    connection.setReadTimeout(readTimeout);
                    stream = connection.getInputStream();
                    image = BitmapFactory.decodeStream(stream, null, options);
                    return image;
                }
            }
            catch (Exception e) {
                Log.e("getImage", e.toString());
            }
        }
        return image;
    }
}

      

It seems that in doInBackground () I am storing the HttpResponseCache and in onPostExecute () I am storing the same image in LRUCache. I would like to do the following:

If the image is not cached, store it in the HttpResponseCache If the HttpResponseCache is full, store it in the LRUCache. If both fields are filled, use the default deletion mechanisms to remove old unused images. The problem is keeping both caches, not

PLAYBACK EDITING QUESTION

**

Since both cache the same image, twice, and store the cache on the same filesystem, perhaps the question should be which one to use, since there seems to be no point in using both ...

**

+3


source to share


1 answer


If anyone wants to reuse any of the above code, I would only take the HTTP response cache and not use the LRU cache, especially if you are caching a web service response, for example. JSON, XML. Why?

I once lost 200MB of device memory due to the LRU cache implementation above.

Benefits of HTTPResponseCache:

  • caches HTTP and HTTPS responses to the file system so they can be reused, saving time and bandwidth.
  • HttpUrlConnection: Automatic handling of caching mechanisms,
  • Speeds up application response times with HttpResponseCache
  • It has been available since API level 1 => it has stood the test of time and is reliable


On the other hand:

While LRUCache has its advantages over DiskLRUCache:

  • You have to implement the class (and other helper classes), that is, if the code in Android developers changes, you will have to constantly download and edit the local version after breaking the application after the previous implementation was deprecated.
  • After deleting the image, you should still be able to find your disk space as the image will be located somewhere on your device (as it was in my case).

This is the conclusion ...

+1


source







All Articles