JakeWharton's DiskLruCache - How to Implement with Volley?
Asked Answered
S

3

1

This is in connection with this question regarding Volley Image caching. So, now I want to implement DiskLruCache, but I am not sure on how to do this.

I downloaded the Jar file from github and added it to my project.

What should I do next? How can I change the existing code of Volley and integrate DiskLruCache?

Existing code:

Initialising Volley:

queue = Volley.newRequestQueue(getActivity());
imageLoader = new ImageLoader(queue, new ImageLoader.ImageCache() {
    private final LruCache<String, Bitmap> mCache = new LruCache<String, Bitmap>(
            10);

    public void putBitmap(String url, Bitmap bitmap) {
        mCache.put(url, bitmap);
    }

    public Bitmap getBitmap(String url) {
        return mCache.get(url);
    }
});

Getting response from server and parsing:

jsArrayRequest = new JsonArrayRequest(url,
        new Response.Listener<JSONArray>() {
            @Override
            public void onResponse(JSONArray response) {
                if (Const.DEBUGGING) {
                    Log.d(Const.DEBUG,
                            "Response => " + response.toString());
                    Log.d(Const.DEBUG, "Length = " + response.length());
                }
                parseResponse(response, url);

                setRetrivalSuccess();
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                if (Const.DEBUGGING) {
                    Log.d(Const.DEBUG, "Volley Error");
                    Log.d(Const.DEBUG, "Error = " + error.toString());
                }

                ((MainFragmentActivity) getActivity())
                        .setSupportProgressBarIndeterminateVisibility(false);

            }
        });
queue.add(jsArrayRequest);

I have seen few examples on SO, but I couldn't understand how to link Volley with DiskLruCache.

Supporter answered 19/2, 2014 at 5:40 Comment(1)
Actually Volley already does some caching to disk, though by default it's only 5MB though and changing it is a bit tedious...Kaiserism
E
5

ImageLoader needs a ImageCache, to use DiskLruCache, you will have to have a wrapper over it which implements ImageCache. VolleyImageCacheExample (Recommended approach is to use basic memory LRU cache as L1 cache and disk cache as L2)

Eczema answered 19/2, 2014 at 7:52 Comment(3)
Thanks for the information. I will go through it and will get back to you.Supporter
Thanks.. it works. I will upvote your answer and provide the solution that I have done as an answer, if thats ok with you.Supporter
It's a bad idea to use a disk cache as an L1 cache, especially when Volley has a built in L2 disk cache, it will create redundancy and bad performance. Use a memory cache for L1, and if you want switch out the built in L2 cache with the DiskLruCache and edit the caching strategy.Antiquary
S
0

I followed the suggestion of kirthika selvaraj, and the VolleyImageCacheExample is working well. I haven't tested it in depth, but it is caching the images well and loading the images from cache when we request the same images second time.

Here is what I have done:

  1. Download the Example/project from this link
  2. Go to Src folder, and copy the following files to your project: RequestManager.java, DiskLruImageCache.java, ImageCacheManager.java
  3. Import all necessary packages (shortcut Ctrl+O if using eclipse)
  4. If you still see the errors, it might be because of package name on the top of these files. Change the package name to your project's package and it should be good.
  5. Download DiskLruCache.jar file(the jar file thats available on github, the versions might change. At this point, it is DiskLruCache-2.0.2.jar) and add it to your libs folder.

The above 4 steps completes the setup. Now the below steps are needed to make it work in your application.

  1. If you have a app file, add the code from MainApplication.java in the example to your app file. If not you can directly add MainApplication.java to your project.
  2. change the place where you add the request object to RequestQueue as follows:

Change this:

queue.add(jsArrayRequest);

to

RequestManager.getRequestQueue().add(jsArrayRequest);

3.In the Adapter for your view(listview/gridview, etc.,) in getView() change the following:

Change this:

image.setImageUrl(imagepath, imageLoader);

to

image.setImageUrl(imagepath, ImageCacheManager.getInstance()
                    .getImageLoader());

This should make it work. Let me know if you have any questions.

Supporter answered 19/2, 2014 at 9:12 Comment(9)
I have added all of three files, but into theDiskLruImageCache.java, I tshows error for DiskLruCache.java. How can i get DiskLruCache.javaDichlorodiphenyltrichloroethane
OK, I think i forgot to mention that. Did you download DiskLruCache.jar file from github.com/JakeWharton/DiskLruCache ? If not download it and add it to the libs folder.Supporter
Mr.Challal I cant find queue.add(jsArrayRequest); in MainApplication.javaDichlorodiphenyltrichloroethane
No its not in MainApplication.java. You must have implemented your request to fetch data from server,somewhere in your project and added that to the RequestQueue object, right? change that line of code.Supporter
@VamsiChalla I followed the above steps and getting error java.lang.IllegalStateException: Not initialized... Please help me to resolve my issue.Tanager
Did you use MainApplication.java? And did you set this application file in android manifest? Not initialized exception means that you haven't initialized the objects correctly. Please recheck your initializationsSupporter
@VamsiChalla I have Appcontroller.java file where I have change the requestqueue and it is mentioned in the manifest file as : android:name= "com.packagename.Appcontroller"Tanager
Can you post your code as question and add the link in the comments here.. I will take a look at it. Post your application class and also activites where you are using the requestqueueSupporter
I will check back in an hour after going to work. Will try to resolve it.Supporter
I
0

Use only one queue for the whole application as a singleton.

    /**
     * Returns an image loader instance to be used with Volley.
     *
     * @return {@link com.android.volley.toolbox.ImageLoader}
     */
    public ImageLoader getVolleyImageLoader()
    {
        if (mImageLoader == null)
        {
            mImageLoader = new ImageLoader
                    (
                            getVolleyRequestQueue(),
                            App.getInstance().getVolleyImageCache()
                    );
        }

        return mImageLoader;
    }

    /**
     * Returns a Volley request queue for creating network requests
     * @return {@link com.android.volley.RequestQueue}
     */
    public RequestQueue getVolleyRequestQueue()
    {
        if (mRequestQueue == null)
        {
            mRequestQueue = Volley.newRequestQueue(this, new OkHttpStack(new OkHttpClient()));
        }
        return mRequestQueue;
    }

    /**
     * Returns a bitmap cache to use with volley.
     *
     * @return {@link LruBitmapCache}
     */
    private LruBitmapCache getVolleyImageCache()
    {
        if (mLruBitmapCache == null)
        {
            mLruBitmapCache = new LruBitmapCache(mInstance);
        }
        return mLruBitmapCache;
    }

Volley does not provide us with an implementation but we can get one from here that looks appropriate and handles the cache size per device specs, which is cool.

import android.graphics.Bitmap;
import android.support.v4.util.LruCache;
import android.util.DisplayMetrics;
import com.android.volley.toolbox.ImageLoader.ImageCache;

public class LruBitmapCache extends LruCache<String, Bitmap>
        implements ImageCache {

    public LruBitmapCache(int maxSize) {
        super(maxSize);
    }

    public LruBitmapCache(Context ctx) {
        this(getCacheSize(ctx));
    }

    @Override
    protected int sizeOf(String key, Bitmap value) {
        return value.getRowBytes() * value.getHeight();
    }

    @Override
    public Bitmap getBitmap(String url) {
        return get(url);
    }

    @Override
    public void putBitmap(String url, Bitmap bitmap) {
        put(url, bitmap);
    }

    // Returns a cache size equal to approximately three screens worth of images.
    public static int getCacheSize(Context ctx) {
        final DisplayMetrics displayMetrics = ctx.getResources().
                getDisplayMetrics();
        final int screenWidth = displayMetrics.widthPixels;
        final int screenHeight = displayMetrics.heightPixels;
        // 4 bytes per pixel
        final int screenBytes = screenWidth * screenHeight * 4;

        return screenBytes * 3;
    }
}

If you have more doubts about how to implement this just check out this article that I've written about it.

Ivers answered 13/7, 2015 at 14:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.