Preload Multiple Images with Glide

Preload multiple images with Glide

The best option is to handle caching yourself, it gives you more control & should be easy as you already know what bitmaps are to be loaded.

First: Setup a LruCache

LruCache<String, Bitmap> memCache = new LruCache<>(size) {
@Override
protected int sizeOf(String key, Bitmap image) {
return image.getByteCount()/1024;
}
};

Second: Load the bitmaps to the LruCache

Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x; //width of screen in pixels
int height = size.y;//height of screen in pixels
Glide.with(context)
.load(Uri.parse("file:///android_asset/imagefile"))
.asBitmap()
.fitCenter() //fits given dimensions maintaining ratio
.into(new SimpleTarget(width,height) {
// the constructor SimpleTarget() without (width, height) can also be used.
// as suggested by, An-droid in the comments
@Override
public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) {
memCache.put("imagefile", resource);
}
});

Third: Use the cached bitmaps

Bitmap image = memCache.get("imagefile");
if (image != null) {
//Bitmap exists in cache.
imageView.setImageBitmap(image);
} else {
//Bitmap not found in cache reload it
Glide.with(context)
.load(Uri.parse("file:///android_asset/imagefile"))
.into(imageView);
}

Glide: How to preload Images and get confirmation that it is stored in cache?

As I understand, the question is: how to preload images with Glide? It wasn't clear before all the conversation happened.

This is actually quite simple and almost identical to loading an image into an ImageView. Glide has a preload() function available that will preload image from given URL. Select DiskCacheStrategy that is most likely fits your situation.

Glide.with(context) 
.load(imageUrl)
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.preload();

Use preload(int width, int height) if you want to change the size of the resulting image.

Glide.with(context) 
.load(imageUrl)
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.preload(width, height);

If your cached images do not actually cache follow this solution to add custom LruCache map.

A little test conducted

A test involved three different sizes ImageViews 100x100, 200x200 and 300x300 DP respectively. Glide was tasked to load an 8K image into 200x200dp ImageView. Then after a short delay load the same image into the 100x100dp ImageView and after another delay into 300x300dp ImageView.

The test shows that the original image was cached due to instant loading speed into 300x300dp ImageView.

Note: Toast messages pop-up right before the image loading starts.

Video proof:

(If the video link is broken try this link).

Glide 8K image loading and caching test

Update (a bit out of question scope): how to wait until all images are preloaded?

... rest of YourActivity class

private int imagesLoaded = 0;
private int totalImagesCount = 0;

private void preloadAllImages(ArrayList<String> imagesUrls) {
totalImagesCount = imagesUrls.size();
for (String url : imagesUrls) {
preloadImage(url);
}
}

private void preloadImage(String url) {
Glide.with(this)
.load(url)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.listener(new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
// Handle exceptions differently if you want
imagesLoaded++;
if (imagesLoaded == totalImagesCount) {
startMainActivity();
}
return true;
}

@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
imagesLoaded++;
if (imagesLoaded == totalImagesCount) {
startMainActivity();
}
return true;
}
})
.preload();
}

Display multiple image with Glide

You no need to worry about memory issue while using glide because glide has own caching system to optimize memory pls read this doc

Glide provides a number of options that allow you to choose how loads will interact with Glide’s caches on a per request basis.

Disk Cache Strategies
DiskCacheStrategy can be applied with the diskCacheStrategy method to an individual request. The available strategies allow you to prevent your load from using or writing to the disk cache or choose to cache only the unmodified original data backing your load, only the transformed thumbnail produced by your load, or both.

The default strategy, AUTOMATIC, tries to use the optimal strategy for local and remote images. AUTOMATIC will store only the unmodified data backing your load when you’re loading remote data (like from URLs) because downloading remote data is expensive compared to resizing data already on disk. For local data AUTOMATIC will store the transformed thumbnail only because retrieving the original data is cheap if you need to generate a second thumbnail size or type.

To apply a DiskCacheStrategy:

GlideApp.with(fragment)
.load(url)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(imageView);

Loading only from cache
In some circumstances you may want a load to fail if an image is not already in cache. To do so, you can use the onlyRetrieveFromCache method on a per request basis:

GlideApp.with(fragment)
.load(url)
.onlyRetrieveFromCache(true)
.into(imageView);

If the image is found in the memory cache or in the disk cache, it will be loaded. Otherwise, if this option is set to true, the load will fail.

How to load image using glide in advance?

You can use this to fine-tune your preloading. It requires quite a bit of work but looks promising.

In short, you need to create a PreLoader class that will get image URLs from your data set:

private class MyPreloadModelProvider implements PreloadModelProvider {
@Override
@NonNull
public List<U> getPreloadItems(int position) {
String url = myUrls.get(position);
if (TextUtils.isEmpty(url)) {
return Collections.emptyList();
}
return Collections.singletonList(url);
}

@Override
@Nullable
public RequestBuilder getPreloadRequestBuilder(String url) {
return
GlideApp.with(fragment)
.load(url)
.override(imageWidthPixels, imageHeightPixels);
}
}

And then you set it as a scroll listener on your recycler view:

PreloadSizeProvider sizeProvider = 
new FixedPreloadSizeProvider(imageWidthPixels, imageHeightPixels);
PreloadModelProvider modelProvider = new MyPreloadModelProvider();
RecyclerViewPreloader<Photo> preloader =
new RecyclerViewPreloader<>(
Glide.with(this), modelProvider, sizeProvider, 10 /*maxPreload*/);

RecyclerView myRecyclerView = (RecyclerView) result.findViewById(R.id.recycler_view);
myRecyclerView.addOnScrollListener(preloader);

After this, you'll get your images preloaded before the onBondViewHolder callback in the adapter, and you'll be able to display them from the cache.

@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
ImageView imageView = ((MyViewHolder) viewHolder).imageView;
String currentUrl = myUrls.get(position);

GlideApp.with(fragment)
.load(currentUrl)
.override(imageWidthPixels, imageHeightPixels)
.into(imageView);
}

Glide - how to load multiple images in parallel?

The solution is manually set pool executors for Glide (and optionally for OkHttp):

public class MyGlideModule implements GlideModule {

@Override
public void applyOptions(Context context, GlideBuilder builder) {
builder.setResizeService(new FifoPriorityThreadPoolExecutor(100));
}

@Override
public void registerComponents(Context context, Glide glide) {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectionPool(new ConnectionPool(100, 3, TimeUnit.SECONDS));
OkHttpUrlLoader.Factory factory = new OkHttpUrlLoader.Factory(builder.build());
glide.register(GlideUrl.class, InputStream.class, factory);
}

}

By default Glide uses thread pool with size, which equals count of CPU cores. So if it detects just 1 core, it will do only one load a time.

You can define as many threads in pool, as you want (here 100, for example).

In turn, OkHttp also has default limitation on connections pool, and it is not so mush, as you may expect (I found just 4 on emulator). You can increase this limit by passing connection pool object with custom parameters to OkHttp builder.

Load multiple images with Glide on Android

So, the only one way to load images with Glide is to load them one by one using Glide.with(ctx).load(File file)...
But it's not a problem to use it even if we have a lot of images - it works perfectly. And it seems that Google Photo app for Android uses Glide, that's why Google recommend using it.



Related Topics



Leave a reply



Submit