在壁画中缓存GIF

时间:2016-01-26 13:14:14

标签: android caching android-recyclerview gif fresco

我正在尝试使用GIF进行回收查看。一切都显示完美,但壁画不缓存GIF。向下滚动回收器并再次向上滚动后,再次加载GIF。我认为它们应该被缓存并加载更快一点。以前我使用ION library。加载速度更快,没有缓存问题。我不得不改变lib,因为它有一些gif解码的问题,描述为here。目前的解决方案如下:

//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"

我还没有看到任何关于不缓存动画图片的信息。有关动画不支持图像后处理的信息,但它的一切都是关于它的。如何正确缓存GIF?

修改 它看起来像壁画缓存动画,因为对于重新加载的GIF,下面的方法返回true。

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);
}

3 个答案:

答案 0 :(得分:1)

为了让事情更加清晰,Fresco有3个级别的缓存:

  • DiskCache - 以原始格式保留图像文件。 (成为 精确,如果在Android版本上并不完全支持webp 图像,它们可以在存储之前转码为其他格式。)
  • EncodedMemoryCache - 原始编码格式的图像的内存缓存。 (图像保存为原始字节的字节数组 因为它们存储在磁盘上+一些额外的元数据。)
  • BitmapMemoryCache - 内存缓存,主要由Android位图组成。位图是解码图像,每个像素占用32位 这比编码时要多得多。

权衡显然是空间与时间的关系。可用内存有限,如果图像不在位图缓存中,则必须再次进行解码。此外,如果它不在编码的内存缓存中,则必须从磁盘读取,这也可能很慢。

现在回到动画图片。这是一个已知的限制。动画图像不会以其解码形式进行缓存,因为这会耗尽位图缓存(只需将num_frames * width * height * 32bpp相乘),并且单个动画图像可能会逐出缓存中的每个其他图像。相反,它们是按需解码的,只有几个即将显示的帧保存在短期缓存中。

我们有一些计划来改进动画,但我无法提供任何时间估算。

答案 1 :(得分:0)

我遇到了同样的问题,看起来Fresco正确地缓存了gif图像,但实际上每次滚动RecyclerView或任何其他视图时,它都需要时间来解码和播放动画。 39;重新使用。 但是,如果你使用没有动画的gif图像,gif图像就不会重新加载"滚动视图时。

因为我可以控制我的应用程序中显示的图像。我在我的服务器上创建了两个版本的gif图像,第一个没有动画显示在RecyclerView / ListView内部,另一个显示在"媒体查看器内#34;活动,当用户点击列表中的项目时。

答案 2 :(得分:0)

Fresco,他们主要关注低尺寸的GIF。我在recycleview中尝试使用低尺寸的GIF,缓存工作完美。如果使用高分辨率的GIF,则需要高内存消耗才能进行解码和缓存。可能超过堆大小。因此它们按需解码,只有几帧(即将显示的帧)被缓存。

可以配置fresco一旦可用就显示第一帧(不解码整帧)并轻松缓存静态第一帧。

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