문제

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.

도움이 되었습니까?

해결책

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)

다른 팁

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.

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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top