5Answers
  • 4
name

A PHP Error was encountered

Severity: Notice

Message: Undefined index: userid

Filename: views/question.php

Line Number: 191

Backtrace:

File: /home/prodcxja/public_html/questions/application/views/question.php
Line: 191
Function: _error_handler

File: /home/prodcxja/public_html/questions/application/controllers/Questions.php
Line: 433
Function: view

File: /home/prodcxja/public_html/questions/index.php
Line: 315
Function: require_once

name Punditsdkoslkdosdkoskdo

Preload multiple images with Glide

We are trying to preload images into cache memory to load them later (the images are located in the Asset folder of the application)

What we tried:

Glide.with(this)
    .load(pictureUri)
    .diskCacheStrategy(DiskCacheStrategy.ALL);

Glide.with(this)
    .load(picture_uri)
    .diskCacheStrategy(DiskCacheStrategy.ALL)
    .preload();

The issue: Images are cached only when we are trying to load/display them: They have to be loaded in memory before so that they appear faster.

Glide.with(this)
    .load(picture_uri)
    .into(imageView);

We also tried to use a GlideModule to increase the CacheMemory size:

public class GlideModule implements com.bumptech.glide.module.GlideModule {
    @Override
    public void applyOptions(Context context, GlideBuilder
        builder.setMemoryCache(new LruResourceCache(100000));
    }

    @Override
    public void registerComponents(Context context, Glide glide) {
    }
}

In the manifest:

 <meta-data android:name=".GlideModule" android:value="GlideModule"/>

Nothing is working so far. Any idea?


We trying to use an invisible 1 dp imageView, but the result is the same:

for(Drawing drawing: getDrawingsForTab(tab)){

    Glide.with(this)
            .load(drawing.getImage().toUri())
            .dontAnimate()
            .diskCacheStrategy(DiskCacheStrategy.ALL)
            .into(mPreloadCacheIv);

    for(Picture picture : getPictures()){

        Glide.with(this)
                .load(picture.getPicture().toUri())
                .dontAnimate()
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .into(mPreloadCacheIv);
    }
}
    • I updated the question with your advice. It's still not working. Glide documentation is not very clear on that subject :/
      • 2
    • I have not used Glide. If your images are assets, I am not quite certain why you are configuring diskCacheStrategy(), as the images are already on disk. Are you sure that your memory cache is being recognized by Glide?
      • 1
    • From the assets the images take too long to load into the ImageView. Once they have been loaded once into memory it's immediat. What i'm trying to acheive is the second behavior for the first time the image is loaded. Do I have a way of knowing in which state is the memory cache ?

Use the following code to cache images without displaying them

  1. using the downloadOnly method if you are looking to download images from the web and store them in the diskCache:

    FutureTarget<File> future = Glide.with(applicationContext)
        .load(yourUrl)
        .downloadOnly(500, 500);
    
  2. using preload method if you want to load them into the Memory Cache.

    Glide.with(context)
            .load(url)
            .preload(500, 500);
    

You can later use the cached images using

Glide.with(yourFragment)
    .load(yourUrl)
    .into(yourView);

  • 33
Reply Report
      • 2
    • I guessed that you want to download the images from web. The API seems to be for "downloadOnly" so i guess the answer is no. Regardless, as i understand, you are looking to load images from assets into the MemoryCache?
      • 1
    • Yes that's the case, I didn't spécify it in the question (I'll edit it). I just need the images to be available into memory for a faster loading and avoid 1, 2 secs between the click and their apparence. Would you know any trick to do that ? With glide or not ?
      • 2
    • When I say it's not working, I mean the image takes the same amount of time to load. Yes I tried to use a glide module with some LruResourceCache as described in the question
    • You should use GlideApp.with(yourFragment).load(yourUrl).fitCenter().asBitmap().preload(); to fix cache missies.

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);
}
  • 20
Reply Report
    • It isn't a good practice to flood all of your memory with bitmaps, ideally you should not exceed more than a quarter of the memory allocated to your application (int) (Runtime.getRuntime().maxMemory() / (1024 * 4)) if you are needing a cache larger than that, you should try a different architectural approach.
    • Another thing, the sizeOf(String key, Bitmap image) method is unknown to glide. It only have getSize(Object item) ?
    • Your response is good, for information it's also possible to use new SimpleTarget() withou specifying values which keep the original size. That's what i've done:)

Glide version 4.6.1

RequestOptions requestOptions = RequestOptions
        .diskCacheStrategy(DiskCacheStrategy.ALL);

Glide.with(appContext)
        .asBitmap()
        .load(model)
        .apply(requestOptions)
        .submit();
  • 10
Reply Report

As the downloadOnly function is deprecated to cache on Disk:

Glide.with(ctx)
        .load("Image URL")
        .downloadOnly(500, 500)

We can now use:

Glide.with(ctx)
        .downloadOnly()
        .load("Image URL")
        .submit(500, 500)
  • 3
Reply Report
//i can give you a solution

/**
 * 1.reflect some objects inside Glide
 */
fun prepareGlideObjects() {
    if (!enableFunctions || atomicPrepare.getAndSet(true)) {
        return
    }
    var t = LogTime.getLogTime()
    glide = Glide.get(BasicConfig.getInstance().appContext)
    if (diskCache == null) {
        val engine = getObject(glide, "engine")
        val diskCacheProvider = getObject(engine, "diskCacheProvider")
        val method = diskCacheProvider!!::class.java.getDeclaredMethod("getDiskCache")
        method.isAccessible = true
        diskCache = method.invoke(diskCacheProvider) as DiskCache
    }
    if (arrayPool == null) {
        arrayPool = getObject(glide, "arrayPool") as ArrayPool
    }
    if (decoder == null) {
        val registry = getObject(glide, "registry") as Registry
        val decoderRegistry = getObject(registry, "decoderRegistry") as ResourceDecoderRegistry
        val map = getObject(decoderRegistry, "decoders") as HashMap<*, *>
        val list = map["Bitmap"] as List<*>
        val o = list[0]
        decoder = getObject(o, "decoder") as ByteBufferBitmapDecoder
    }
    Log.debug(TAG, "prepareGlideObjects:" + LogTime.getElapsedMillis(t))
    try {
        t = LogTime.getLogTime()
        //????diskCache ????????????????
        val url = GlideUrl("http://xx.cdn.yy.com/fake_pic.jpg")
        val dataCacheKey = DataCacheKey(url, EmptySignature.obtain())
        diskCache?.get(dataCacheKey)
        Log.debug(TAG, "_load_fake_pic:" + LogTime.getElapsedMillis(t))
    } catch (e: Throwable) {
        Log.error(TAG, "cold load failed:$e")
    }
}

/**
 *2.load bitmap-file from diskCache
 */
fun loadBitmap(url: String) {
    val gUrl = GlideUrl(url:String)
    val dataCacheKey = DataCacheKey(gUrl, EmptySignature.obtain())
    val file = diskCache?.get(dataCacheKey)
}

//3.decode bitmap from file
private fun extractBitmapFromFile(url: String, file: File) {
    try {
        val dimen = getDimensionFromUrl(url)
        val result = decoder?.decode(ByteBufferUtil.fromFile(file), dimen[0], dimen[1],
                Options()) as BitmapResource?
        result!!.initialize()
        //simple bitmap cache
        bitmapMap[url] = result.get()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            Log.debug(TAG, "allocationByteCount:" +
                    bitmapMap[url]!!.allocationByteCount / 1024.0)
        }
    } catch (e: Throwable) {
        Log.error(TAG, "init result failed:$e")
    }
}

//4.decode file from http-stream
private fun decodeHttpStream() {
    val uri = GlideUrl(call?.request()?.url().toString())
    val contentLength = Preconditions.checkNotNull(responseBody).contentLength()
    val stream = ContentLengthInputStream.obtain(responseBody.byteStream(),
            contentLength)
    if (arrayPool == null) {
        //re prepare
        arrayPool = glide?.arrayPool
    }
    val encoder = StreamEncoder(arrayPool)
    val writer = DataCacheWriter(encoder, stream, Options())
    val originalKey = DataCacheKey(uri, EmptySignature.obtain())
    //ready,??????????????????????
    diskCache?.put(originalKey, writer)
    val file = diskCache?.get(uri)
}

//5.after these jobs done, load a bitmap from diskCache,it takes just 10ms?

  • -1
Reply Report