0
votes

I am using Glide v4 for remote image downloading and caching. I want to preload RecyclerView images with Glide and other data (such as text) from server in AsyncTask, displaying a progress bar in the layout instead of RecyclerView. I've done that successfully by using

Drawable drawable = Glide.with(context)
.load(url)
.submit()
.get();

and then storing drawables in memory, applying it to the ImageView in OnBindViewHolder():

imageView.setImageDrawable(drawable);

Hovewer, I understand that storing drawables in memory is ineffective, also disk caching doesn't work, so I decided to try downloading all images to disk cache in AsyncTask by:

Glide.with(context)
.downloadOnly()    
.load(url)
.apply(new RequestOptions().diskCacheStrategy(DiskCacheStrategy.DATA))
.submit();

And then retrieving them in OnBindViewHolder() by:

Glide.with(context)
.load(url)
.apply(new RequestOptions().onlyRetrieveFromCache(true))
.into(imageView);

But the preloading in AsyncTask or loading from disk cache doesn't work, causing images to download from Web after AsyncTask has finished. Log:

Glide: Load failed for http://image.tmdb.org/t/p/w600_and_h900_bestv2/h5n8B12WoY1UAZjzSVEup4vsoBw.jpg with size [255x255] class com.bumptech.glide.load.engine.GlideException: Failed to load resource

From here, I came to conclusion that image loading from disk cache is failing because the size of the view and size of the preloaded image are different. From Glide docs, I assumed that to know the ImageView's size automatically, I need to preload the image into needed ImageView and get the Target object (but I'm not sure about this) by

Target<Drawable> target = Glide.with(context)
.load(url)
.apply(new RequestOptions().diskCacheStrategy(DiskCacheStrategy.DATA))
.into(imageView);

and then retrieve image from cache in OnBindViewHolder() by

Glide.with(context)
.load(url)
.apply(new RequestOptions().onlyRetrieveFromCache(true))
.into(target);

But I don't know how and when to pass references of RecyclerView's ViewHolder ImageView to AsyncTask's doInBackground(), and is it a good practice to pass Views to background threads?

Or perhaps there is a much clearer solution to background caching and then retrieving?

1
Have you tried your first solution with DiskCacheStrategy.ALL ? I believe DiskCacheStrategy.DATA only caches the full size image.Cody W.
@CodyW. Just tried it, doesn't work :(Daniel

1 Answers

0
votes

use IntentService for load image.

public class LoadImage extends IntentService {
private CommonData common;
private final String TAG = "LoadAvatar";

@Override
protected void onHandleIntent(@Nullable Intent intent) {
    String data = intent.getStringExtra("data");
    try {
        JSONObject jsonObject = new JSONObject(data);
        JSONArray jsonArray = jsonObject.getJSONObject("data").getJSONArray("res");
        for (int i = 0; i < jsonArray.length(); i++) {

                JSONObject jObj = jsonArray.getJSONObject(i);
                FutureTarget<File> future = Glide.with(this).load(jObj.getString("url")).downloadOnly(400, 400);
                try {
                    future.get();
                    //stopSelf();
                    break;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    stopSelf();
                    break;
                } catch (ExecutionException e) {
                    e.printStackTrace();
                    stopSelf();
                    break;
                }


        }
    } catch (Exception e) {
       e.printStackTrace();
        stopSelf();
    }
}

}

and call intent service in starting.

  Intent i = new Intent(this, LoadAvatar.class);
  i.putExtra("data", data);
  startService(i);