Fresco图片加载框架的介绍,相关开源库以及工具类的封装
本文已授权微信公众号:鸿洋(hongyangAndroid)在微信公众号平台原创首发。
简介
Fresco 是Facebook开源的安卓上的图片加载框架,也可以说是至今为止安卓上最强大的图片加载框架.
相对于其他几个图片加载框架,Fresco主要的优点在于更好的内存管理和更强大的功能,更便捷的使用,缺点则是体积比较大,引入后会导致应用apk增加1.5M到2M的大小,但是相对于其便捷性来讲,我觉得这都不是事儿.
优点一:内存管理
对于5.0以下系统,fresco使用”ashmem”(匿名共享内存)区域存储Bitmap缓存,这样Bitmap对象的创建、释放将不会触发GC,不会占用javaheap. 这个特点是其他图片加载框架所没有做到的.
5.0以上系统,由于安卓系统本身内存管理的优化,所以对于5.0以上的系统Fresco将Bitmap缓存直接放到了javaheap内存中.
并且,fresco实现了真正的三级缓存:两级的内存缓存+一个磁盘缓存.两个内存缓存为:bitmap缓存 和未解码的图片缓存,这样既可以加快图片的加载速度,又能节省内存的占用.这个两级的内存缓存也是其他图片加载框架所没有做到的.
另外提一点,在app切换到后台时,fresco会自动清理两级的内存缓存,无需手动.
通过以上几点,使用fresco加载图片时内存占用要比其他图片加载框架小一大半,基本很少发生oom的事情.
几个图片加载框架的内存占用测试结果对比请戳这里:Android Image Loader 第三方库对比测试
优点二:更便捷的使用:
初期入门,轻度的图片加载,甚至可以直接用:
Fresco.initiliaze(context);
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/my_image_view"
android:layout_width="20dp"
android:layout_height="20dp"
fresco:placeholderImage="@drawable/news_default"
.../>
simpleDraweeView.setImageURI(uri);
其他都不用管,fresco自动帮我们做缓存,图片缩略.
显示圆角或圆圈图片也只是xml中配置一下而已:
圆圈 - 设置roundAsCircle为true
圆角 - 设置roundedCornerRadius
另外再说一句,fresco还支持webp,所以,splash和引导界面的大图我一般都是用智图压成webp放在drawable中,用fresco加载就行了.
相关文档及开源库
Github开源库:facebook/fresco,已更新到0.10.0
fresco里的photoview :用于查看大图并随手势缩放
bilibili开源的借助fresco加载图片的 spannable text view : Bilibili/drawee-text-view
fresco的bitmap后处理器封装,可以直接使用,关于后处理请看文档
使用心得及一些方法的封装
加载超级大图还是会卡
首先,终极的解决方法肯定是,客户端在图片请求中带上需要的宽和高,服务器将图片缩略到该规格后返回该小图.这个做得比较好的是七牛.
注意:不管服务器能不能返回缩略图,所存储的原图都不应该太大,有时图片太大,甚至都无法下载下来(报504之类的错误).
那么,如果服务器只能拿到原图或大图,fresco怎么缩略显示?
fresco中提供了三个功能来生成缩略图:
Scaling :画布操作,通常是由硬件加速的。图片实际大小保持不变,它只不过在绘制时被放大或缩小.使用时需要配置缩放类型fresco:actualImageScaleType,具体类型名与Imageview的ScaleType几乎一样.
Resizing 是一种软件执行的管道操作。它返回一张新的,尺寸不同的图片,也就是说直接改变bitmap的大小,可惜是单独使用时,只支持jpg,当然,结合Downsampling使用时,可以支持除gif以为的所有常见图片,包括webp.
Downsampling 同样是软件实现的管道操作。它不是创建一张新的图片,而是在解码时改变图片的大小。 同样是软件实现的管道操作。它不是创建一张新的图片,而是在解码时改变图片的大小。类似于android中的BitmapFactory在decodefile时的inSampleSize,都是指定一个采样率,默认是关闭的,如果开启,那么需要结合Resizing来使用.
综上,要缩小内存占用,以及减少cpu计算量,减少卡顿,应该是Downsampling结合Resizing来使用.其中Downsampling是在Fresco初始化时开启,而Resizing则是通过构建ImageRequest时通过制定宽高来实现,所以可以定制每一张或每一类图片的宽高. 示例代码如下
初始化:
/**
* 初始化操作,建议在子线程中进行
* 添加的依赖:
* compile 'com.facebook.fresco:fresco:0.10.0+'
compile 'com.facebook.fresco:animated-webp:0.10.0'//加载webp必须添加
compile 'com.facebook.fresco:animated-gif:0.10.0' //加载gif必须添加
* @param context
* @param cacheSizeInM 磁盘缓存的大小,以M为单位
*/
public static void init(final Context context,int cacheSizeInM){
DiskCacheConfig diskCacheConfig = DiskCacheConfig.newBuilder(context)
.setMaxCacheSize(cacheSizeInM*1024*102