4

I am trying to make a recyclerview with gifs. Everything shows perfectly but fresco do not cache gifs. After scroll recycler down and scroll up again, gifs are loading once again. I supposed they should be cached and loaded a bit quicker. Previously I used ION library. Loading was quicker and did not have cache problem. I had to change lib because, it has some problem with gif decoding, described here. Current solution looks like that:

//for default initial in application class 

Fresco.initialize(this);
//I have also tried to change DiskCacheConfig and ImagePipelineConfig params. 
//Without any positive result

//for recyclerview on onBindViewHolder    
GenericDraweeHierarchy hierarchy = holder.draweeView.getHierarchy();
Uri uri = Uri.parse(path);
hierarchy.setPlaceholderImage(R.drawable.img_bg);
Logger.e(check(uri) + " " + uri.toString());
DraweeController controller = Fresco.newDraweeControllerBuilder().setUri(uri)
            .setAutoPlayAnimations(true).build();
    holder.draweeView.setController(controller);

//for method which show cached uri images in imagepipeline
public static boolean check(Uri uri) {
    ImagePipeline imagePipeline = Fresco.getImagePipeline();
    return imagePipeline.isInBitmapMemoryCache(uri);
}
//... all the time log shows "false + gif url"

I have not seen any information about not caching animated images. There is information about not supported image postprocessing for animations, but it's everything about that. How to correctly cache gifs?

edit: It looks like fresco cache animations, because below method return true for reloaded gifs.

public static boolean isImageDownloaded(Uri loadUri) {
    if (loadUri == null) {
        return false;
    }
    CacheKey cacheKey = DefaultCacheKeyFactory.getInstance()
            .getEncodedCacheKey(ImageRequest.fromUri(loadUri));
    return ImagePipelineFactory.getInstance().getMainDiskStorageCache().hasKey(cacheKey)
            || ImagePipelineFactory.getInstance().getSmallImageDiskStorageCache()
                    .hasKey(cacheKey);
}
BactaTank
  • 164
  • 2
  • 10

3 Answers3

1

Just to make things a bit more clear, Fresco has 3 levels of cache:

  • DiskCache - Keeps image files in their original format. (To be precise, if on an Android version that doesn't fully support webp images, they may be transcoded to other format before storing.)
  • EncodedMemoryCache - In-memory cache of images in their original encoded format. (Image is kept as a byte-array of the original bytes as they are stored on disk + some additional metadata.)
  • BitmapMemoryCache - In-memory cache consisting mostly of Android Bitmaps. Bitmaps are decoded images and each pixel occupies 32bits which is significantly more than what it takes when encoded.

The trade-off is obviously space vs time. Available memory is limited and if the image is not in the bitmap cache, it will have to be decoded again. Furthermore, if it is not in the encoded memory cache either, it will have to be read from the disk which also can be slow.

Now back to the animated images. This is a known limitation. Animated images are not cached in their decoded form because that would exhaust the bitmap cache (just multiply the num_frames * width * height * 32bpp) and a single animated image can possibly evict every other image in the cache. Instead they are decoded on demand and only a couple of frames that are about to be displayed next are kept in a short-lived cache.

We have some plans to improve animations, although I cannot provide any time estimates.

plamenko
  • 1,068
  • 1
  • 8
  • 10
0

I was facing the same issue, it appears that Fresco is correctly caching the gif images, but in fact it's taking time to decode and play the animation each time you scroll through the RecyclerView or any other view you're using. However if you use a gif image without animation, the gif image doesn't "reload" when scrolling through the view.

Since I have control over the images displayed inside my app. I am creating 2 versions of the gif images on my server, the first without animation to display inside the RecyclerView/ListView and the other to display inside the "Media viewer" activity, when the user clicks on an item in the list.

McHeimech
  • 113
  • 1
  • 1
  • 6
0

Fresco, they mainly focused low size gifs. I tried with low size gifs in recycleview, caching working perfectly. If you use high resolution gifs, they need high memory consumption for decode and caching. may be surpass heap size. so they are decoded on demand, and only a couple of frames (those about to be displayed) get cached.

It is possible to configure fresco to display the first frame as soon as it is available (without decode whole frame) and cache the static first frame easily.

        ImageDecodeOptionsBuilder b = new ImageDecodeOptionsBuilder();
        b.setForceStaticImage(true);
        ImageDecodeOptions imageDecodeOptions=new ImageDecodeOptions(b);
        ImageRequest request =  ImageRequestBuilder.newBuilderWithSource(animatedGifUri).setImageDecodeOptions(imageDecodeOptions).setLocalThumbnailPreviewsEnabled(true).build();