How to cache a NetworkImage to use in Another Acti

2019-05-25 08:33发布

I have two views, one is main and the other one detail. I am getting all the urls from the server and display the bitmap accordingly on the gridview. Once users clicks on a grid item, I want to use cache'd image from the main view. However, my following implementation does not work.

The way I am testing is as follows: first, I display all images on the gridview and disconnect the Internet and wanted to see cached image on the detail. However, on the detail activity the image is not being displayed.

I am using the following Volley Singleton class as follows:

public class CustomVolleyRequest {

    private static CustomVolleyRequest customVolleyRequest;
    private static Context context;
    private RequestQueue requestQueue;
    private ImageLoader imageLoader;

    private CustomVolleyRequest(Context context) {
        CustomVolleyRequest.context = context;
        this.requestQueue = getRequestQueue();

        imageLoader = new ImageLoader(requestQueue,
                new ImageLoader.ImageCache() {
                    private final LruCache<String, Bitmap>
                            cache = new LruCache<>(20);

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

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

    public static synchronized CustomVolleyRequest getInstance(Context context) {
        if (customVolleyRequest == null) {
            customVolleyRequest = new CustomVolleyRequest(context);
        }
        return customVolleyRequest;
    }

    public RequestQueue getRequestQueue() {
        if (requestQueue == null) {
            requestQueue = Volley.newRequestQueue(context.getApplicationContext(), 10 * 1024 * 1024);
        }
        return requestQueue;
    }

    ImageLoader getImageLoader() {
        return imageLoader;
    }
}

Main Activity Adapter

public View getView(final int position, View convertView, @NonNull ViewGroup parent) {
    final ViewHolder holder;
    if(convertView == null) {
        holder = new ViewHolder();
        convertView = LayoutInflater.from(getContext()).inflate(R.layout.grid_item, parent, false);
    }
  holder.imageView.setImageUrl(imageRecord.getUrl(), mImageLoader);
}

Detail Activity

String url = getArguments().getString("image_url");
ImageLoader imageLoader = CustomVolleyRequest.getInstance(getContext()).getImageLoader();
mImageView.setImageUrl(url, imageLoader);

1条回答
走好不送
2楼-- · 2019-05-25 09:35

If the size of the ImageView is different the default implementation for image caching will not work as the key of the caches passed by the ImageLoader include the size of the view:

private static String getCacheKey(String url, int maxWidth, int maxHeight, ScaleType scaleType) {
    return "#W" + maxWidth + "#H" + maxHeight + "#S" + scaleType.ordinal() + url;
}

You have 2 main options:

1) Rework the ImageLoader and probably NetworkImageView as it places the actual converted bitmap, which might be different size and you may want to call createScaledBitmap() to adjust it to the view.

2) make sure the raw image data received form the network is cached.

So 1) relatively complex because you have to change a few classes chnage the parsing done in ImageRequest and not to scale the raw image data but perform the scaling after the image is received and cached, basically in NetworkImageView or late in ImageLoader

If you go for 2 you would probably need to adjust the default Network Cache implementation of Volley if you server does not send cache headers or etag. In that case you will need a little change in ImageLoader for that you can check https://stackoverflow.com/a/36549815/2267924

查看更多
登录 后发表回答