一、认识Fresco
说实话,其实我觉得Fresco对大家来说,可能并不陌生,具体介绍的话我就不多说了,而且介绍的文章也不少,我觉得我也没必要再取讲一遍,有兴趣的可以自己阅读官方资料
我自己总结fresco的优点主要就是以下几点:
- 内存管理,相比其他ImageLoader,5.0以下能够自己开辟独立内存存储bitmap对象,减少gc的触发,5.0以上能够利用Android自身的内存优化,存储到heap中。
- 真正的三级缓存机制,实现了了内存的二级缓存以及硬盘的缓存。
- 强大的图片加载处理能力
- 丰富的图片处理能力
- 对gif、webP的支持
总结以上,不愧是Facebook出品的东西,不过我的意思并不是要大家都用fresco,其实也是根据项目的实际情况,来选择合适的开源框架,正好,我遇到的这个项目就比较适合用fresco来实现。
项目需求
先说说需求吧。其实就是listview加载图片的经典问题,像普通的资源管理器,都有分类功能,当查看到视频模块或者图片模块时,为了更直观的现实,一般都是采取加载显示缩略图的方式。
先说说我一开始的想法,我一开始想的是通过图片获取mediastore中的缩略图,然后通过imageview直接显示出来,用的是lrucache来存储缓存。
可能有朋友还不太清楚Android的缩略图机制,是通过ThumbnailUtils来获取,这个是Android2.2之后google官方提供的一个类,它不仅可以获取图片的缩略图,而且还可以获取视频的缩略图,也是一个非常强大的类,具体用法可参考这里:
该做法是通过这个类,获取到图片,转换为bitmap对象,然后对bitmap图像进行压缩处理,并且再通过imageview来加载压缩后的bitmap,这样的做法对于图片不多的情况是足够用的,而且效果也是不错的。
可为什么又要用fresco呢?毕竟之前的做法是自己来管理图片的压缩与加载,碰上有上千张图片,如果在配置不好的机器上,或者写法稍微有点问题,就很容易触发gc,造成界面的卡顿。
悲催的我,今天就试了试用自己的写的框架加载2000+图片,尼玛,没滑动几下,就gg了,肯定是我的代码有问题,但是秉着为了早日完成任务,以后慢慢研究问题代码的原则,毅然决然的用大招-----Fresco登场.
查阅官方文档后就觉得,fresco简直就是专门拿来解决这个问题的:
可以看出,fresco核心是通过uri来加载图片的,任何格式的文件,都可以通过转化为uri来加载显示。
既然是加载本地文件显示,总不可能直接让fresco直接加载file吧?
我试了试,通过file转化为uri来加载显示,尼玛。。卡死我了,缩略图的view本来就小,硬是把几M的东西加载到及时px的东西上,换谁谁都卡。
具体使用
所以我觉得这时候就应该显示fresco强大的加载功能的时候了。
fresco提供缩放图片的功能:
- Scaling 是一种画布操作,通常是由硬件加速的。图片实际大小保持不变,它只不过在绘制时被放大或缩小。
- Resizing 是一种软件执行的管道操作。它返回一张新的,尺寸不同的图片。
- Downsampling 同样是软件实现的管道操作。它不是创建一张新的图片,而是在解码时改变图片的大小。
我不通过ThumbnailUtils来获取图片的缩略图,我可以直接利用fresco解码时,设置好缩放参数,得到缩略图大小尺寸分辨率的小图来显示,毕竟只是展示缩略图。
所以当然选择的方式是Resizing+Downsampling方式来实现。
为什么呢?
因为Resizing实际上就相当于ThumbnailUtils的操作,返回一张新的,尺寸不同的图片,也就是说直接修改了bitmap的大小,但是单独使用时,仅仅支持jpg格式,查阅官方文档时,只要在配置时加上Downsampling的开启,便可支持除gif以外的所有格式图片。
所以我觉得这两个功能简直就是为了缩略图而生的功能。
看看具体怎么使用:
- 首先得在application里设置好自定义的缓存机制
ImagePipelineConfig config = ImagePipelineConfig.newBuilder(context) .setBitmapMemoryCacheParamsSupplier(bitmapCacheParamsSupplier)
.setCacheKeyFactory(cacheKeyFactory)
.setDownsampleEnabled(true)
.setWebpSupportEnabled(true) .setEncodedMemoryCacheParamsSupplier(encodedCacheParamsSupplier)
.setExecutorSupplier(executorSupplier) .setImageCacheStatsTracker(imageCacheStatsTracker) .setMainDiskCacheConfig(mainDiskCacheConfig) .setMemoryTrimmableRegistry(memoryTrimmableRegistry) .setNetworkFetchProducer(networkFetchProducer) .setPoolFactory(poolFactory) .setProgressiveJpegConfig(progressiveJpegConfig) .setRequestListeners(requestListeners) .setSmallImageDiskCacheConfig(smallImageDiskCacheConfig)
.build();
Fresco.initialize(context, config);
可以看到通过builder模式,我们可以自由的配置fresco的各种参数,包括图片下载的监听、缓存的命中率 、缓存的的位置、缓存的策略,当然还包括我们要设置的setDownsampleEnabled(),具体可以参看官方配置指导,这里我就不一一写出。
Uri uri = "file:///mnt/sdcard/MyApp/myfile.jpg";
int width = 50, height = 50;
ImageRequest request =ImageRequestBuilder
.newBuilderWithSource(uri)
.setResizeOptions(new ResizeOptions(width, height))
.build();
PipelineDraweeController controller = Fresco.newDraweeControllerBuilder() .setOldController(mDraweeView.getController()) .setImageRequest(request)
.build();
mSimpleDraweeView.setController(controller);
通过这简单的几行代码,我们设置好后,就可以对本地文件进行压缩显示。
实际上,还可以直接加载视频的uri,fresco会自动截取视频的一帧来进行压缩处理,和图片的效果是一样的。
没错,就是这么简单,就是这么方便,这里并不打算写长篇大论来解读原理,等我读完源码再来写。
我觉得,工具库的诞生,就是为了简化我们的开发,避免重复早轮,但是造轮子的能力还是得有的,有机会我要研究研究怎么造出的这个轮子。
哈哈,试了试效果,那流畅度简直是不能忍呀!
并且我们还可以通过
Fresco.getImagePipeline().pause()和resume()
方法来配合listview滑动停止加载和开启等功能,简直不能再爽。
当然,fresco不止有这些功能,还有例如圆角、渐变、高斯模糊等功能,有兴趣可以自行查阅。
总结
希望这篇文章对有需要的童鞋有所帮助,也是自己的一篇笔记吧,有机会再深入研究研究fresco这个神器。