0

I'm trying to create a RecyclerView that is populated by ImageViews in each cell and each image corresponds to an image in Firebase Storage. I have a list of Strings that is passed into my RecyclerView adapter and each one represents a URL to an image in Firebase Storage. I load each image inside the onBindViewHolder().

What i get in return is a very VERY slow loading of a few images (around 5-see picture) and then it takes around 4 minutes to load another 5 and it never seems to load any other images after these.

I've read multiple posts on StackOverflow but most of them just tell you to use fitCenter() or centerCrop() but that doesn't change anything in my case. I also read in Glide's documentation that Glide will automatically downsample your images so i shouldn't need to do it manually, right? Any ideas what i could be doing wrong here? The Url Strings are successfully retrieved from Firebase and the queries are resolved almost instantly so i don't think there is any issue there.

UPDATE: I've made some modifications in the onBindViewHolder() method in order to explicitly request caching of the images from Glide and i also used the thumbnail API to download lower resolutions of the images. Now more images are loading but each one still takes around 7 seconds to load which obviously is too long. If you have any suggestions let me know please.

Here's how the RecyclerView is set up in my main activity:

iconsRCV = findViewById(R.id.cardIconsRCV)
iconsRCV.layoutManager = GridLayoutManager(this,5) // set the layout manager for the rcv
val iconUrls : ArrayList<String> = ArrayList() // initialize the data with an empty array list
val adapter = CardIconAdapter(this,iconUrls) // initialize the adapter for the recyclerview
iconsRCV.adapter = adapter // set the adapter

Note that i get new data when certain queries are done and then i call adapter.notifyDataSetChanged() to pass new data to the RecyclerView.

CardIconAdapter.java:

public class CardIconAdapter extends RecyclerView.Adapter<CardIconAdapter.ViewHolder> {

private  RequestOptions requestOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL).centerCrop().error(R.drawable.applogotmp);
private List<String> urlsList;
private Context context;

class ViewHolder extends RecyclerView.ViewHolder {
    ImageView iconImg;
    ViewHolder(@NonNull View view) {
        super(view);
        iconImg = view.findViewById(R.id.cardIcon);
    }
}

public CardIconAdapter(Context cntxt, List<String> data) {
    context = cntxt;
    urlsList = data;
}

@NonNull
@Override
public CardIconAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View view =  LayoutInflater.from(parent.getContext()).inflate(R.layout.card_icons_rcv_item,parent,false);
    return new ViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull CardIconAdapter.ViewHolder holder, int position) {
    GlideApp.with(context).load(urlsList.get(position)).apply(requestOptions).into(holder.iconImg);
}

@Override
public int getItemCount() {
    return urlsList.size();
}
}

result

P.S. The image sizes in Firebase are mostly udner 200KB but with a small few reaching 4MB. Also, the ImageView in the R.layout.card_icons_rcv_item layout is 75x75 in size.

Stelios Papamichail
  • 955
  • 2
  • 19
  • 57
  • have you tried to cache images using glide? – Radhey Nov 21 '19 at 11:32
  • @Radhey doesn't glide automatically cache them? – Stelios Papamichail Nov 21 '19 at 11:39
  • have you tried to load images with smaller size? – Alexandr Kolesnik Nov 21 '19 at 12:19
  • yes, it will automatically manage but depends on glide version too. for reference https://android.jlelse.eu/best-strategy-to-load-images-using-glide-image-loading-library-for-android-e2b6ba9f75b2 also use `diskCacheStrategy(DiskCacheStrategy.ALL)` and `thumbnail API `. – Radhey Nov 21 '19 at 12:29
  • @AlexandrKolesnik you mean manually downsample them in code? I tried that in another question here but i didn't see much of an improvement. Shouldn't Glide automatically downsample them though per the documentation? – Stelios Papamichail Nov 21 '19 at 12:35
  • @Radhey thank you, the link really helped. I've updated my post. I used both the thumbnail API & the explicit caching of images and although more images are now loading successfully, each one still takes more than 7 seconds to load which is still really slow. Any other ideas? – Stelios Papamichail Nov 21 '19 at 12:54
  • you can set default `place holder` or `progress bar` using glide's method too. use `dontTransform()` that increase your speed while loading – Radhey Nov 22 '19 at 05:37
  • 1
    @Radhey that improved the loading a lot. Would you mind submitting and answer and also checking my latest question about some RecyclerView issues i came across here : https://stackoverflow.com/questions/59002056/poor-performance-on-recyclerview-when-using-pagination-of-data-from-firebase ? – Stelios Papamichail Nov 22 '19 at 21:36

1 Answers1

2

Hope you have used latest version of glide. There are few ways for better image loading and caching, credit goes to this nice article .

1. Enable Disk Cache

 val requestOptions = RequestOptions().diskCacheStrategy(DiskCacheStrategy.ALL)
 Glide.with(context).load(url).apply(requestOptions).into(imageView)

2. List item

val requestOptions = RequestOptions()
        .diskCacheStrategy(DiskCacheStrategy.ALL)
        .signature(ObjectKey(signature))

Glide.with(context).load(url).apply(requestOptions).into(imageView)

3. Override Image Size (Optional)

val requestOptions = RequestOptions()
        .diskCacheStrategy(DiskCacheStrategy.ALL)
        .signature(ObjectKey(signature))
        .override(100, 100) // resize does not respect aspect ratio

Glide.with(context).load(url).apply(requestOptions).into(imageView)

4. Add Thumbnail Url

// With thumbnail url
Glide.with(context).load(url)
        .thumbnail(Glide.with(context).load(thumbUrl))
        .apply(requestOptions).into(imageView)

// Without thumbnail url

// If you know thumbnail size
Glide.with(context).load(url)
        .thumbnail(Glide.with(context).load(url).apply(RequestOptions().override(thumbSize)))
        .apply(requestOptions).into(imageView)

// With size multiplier
Glide.with(context).load(url)
        .thumbnail(0.25f)
        .apply(requestOptions).into(imageView)

5. Setup Monthly Schedule for Cleaning

// This method must be called on the main thread.
Glide.get(context).clearMemory()

Thread(Runnable {
    // This method must be called on a background thread.
    Glide.get(context).clearDiskCache()
}).start()

6. To Transform bitmap

      // TODO remove after transformation is done
        .diskCacheStrategy(SOURCE) // override default RESULT cache and apply transform always
        .skipMemoryCache(true) // do not reuse the transformed result while running
        .diskCacheStrategy(DiskCacheStrategy.ALL) // It will cache your image after loaded for first time
        .format(DecodeFormat.PREFER_ARGB_8888) //for better image quality
        .dontTransform() // to load image faster just skip transform 
        .placeholder(R.drawable.placeholder) // use place holder while image is being load
Radhey
  • 2,139
  • 2
  • 24
  • 42
  • This is actually everything the article you linked in the comment section says. Sadly, as i mention in the comments none of these made the loading any faster – Stelios Papamichail Nov 28 '19 at 14:55
  • 1
    it isn't any issue in glide implementation . you are creating `requestOptions` object every times inside onBindViewHolder() of adapter class. make that object at class level globally and check it again. – Radhey Nov 28 '19 at 19:05
  • Hmm, seems like things are loading faster now but still take 1-2 seconds for each icon which seems pretty slow still right? They seem to be loading sequentially, can't they be loaded in parallel somehow? I'm wondering how do apps like reddit,facebook,imgur etc. load images so fast and in such high res? – Stelios Papamichail Nov 28 '19 at 21:08
  • I just post max strategies that one can find over stackoverflow not form blog directly. you can accept the answer if it improvised your loading timing. hence you need to change your adapter code.let me check. – Radhey Nov 29 '19 at 04:51
  • can you update your question with adapter and glide implementation again what you have tried at the end! – Radhey Nov 29 '19 at 09:19