Fresco介绍、Fresco VS Glide多维度对比
一、Fresco概述(来自Fresco官网)
是一个强大的图片加载组件。使用它之后,你不需要再去关心图片的加载和显示这些繁琐的事情!它负责从网络,从本地文件系统,本地资源加载图片并且显示一个占位符直到图片现在完成。它有两个等级的缓存,一个是在内存中,另一个在内部存储。在Android4.x以及更低系统,Fresco 将图片放在Android 内存中的一个特殊区域。 这可以使你的应用程序运行的更快,并且遭受更少的OutOfMemoryError。
Fresco的开源地址是,[https://github.com/facebook/fresco]
Fresco主要模块
1.Image Pipeline
Fresco 中设计有一个叫做 Image Pipeline 的模块。它负责从网络,从本地文件系统,本地资源加载图片。为了最大限度节省空间和CPU时间,它含有3级缓存设计(2级内存,1级磁盘)。
2.Drawees
Fresco 中设计有一个叫做 Drawees 模块,它会在图片加载完成前显示占位图,加载成功后自动替换为目标图片。当图片不再显示在屏幕上时,它会及时地释放内存和空间占用。
二、Fresco特性(来自Fresco官网)
1.内存管理
解压后的图片,即Android中的Bitmap,占用大量的内存。大的内存占用势必引发更加频繁的GC。在5.0以下,GC将会显著地引发界面卡顿。
在Android 4.x以及更低系统,Fresco将图片放到一个特别的内存区域。当然,在图片不显示的时候,占用的内存会自动被释放。这会使得APP更加流畅,减少因图片内存占用而引发的OOM。
Fresco 在低端机器上表现一样出色,你再也不用因图片内存占用而思前想后。
2.图片加载
Fresco的Image Pipeline允许你用很多种方式来自定义图片加载过程,比如:
(1).为同一个图片指定不同的远程路径,或者使用已经存在本地缓存中的图片
(2).先显示一个低清晰度的图片,等高清图下载完之后再显示高清图
(3).加载完成回调通知
(4).对于本地图,如有EXIF缩略图,在大图加载完成之前,可先显示缩略图
(5).缩放或者旋转图片
(6).对已下载的图片再次处理
(7).支持WebP解码,即使在早先对WebP支持不完善的Android系统上也能正常使用!
3.图片绘制
Fresco 的 Drawees 设计,带来一些有用的特性:
(1).自定义居中焦点
(2).圆角图,当然圆圈也行
(3).下载失败之后,点击重现下载
(4).自定义占位图,自定义overlay, 或者进度条
(5).指定用户按压时的overlay
4.图片的渐进式呈现
渐进式的JPEG图片格式已经流行数年了,渐进式图片格式先呈现大致的图片轮廓,然后随着图片下载的继续,呈现逐渐清晰的图片,Android 本身的图片库不支持此格式,但是Fresco支持。
5.动图加载
处理好每一帧并管理好你的内存
三、Fresco具体使用
1.配置环境
compile 'com.facebook.fresco:fresco:0.13.0'
2.Fresco 初始化
Fresco.initialize(context);
3.控件
Fresco 是使用SimpleDraweeView控件来显示图片的。在布局文件中添加SimpleDraweeView控件,代码例如:
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/idrawee_view"
android:layout_width="100dp"
android:layout_height="100dp" />
注意 记得使用 SimpleDraweeView时
1.宽高要设置为一个具体的值,
2.也可以在代码中设置宽高或者宽高比,但是宽高不能都是 wrap_content。
只有希望显示固定的宽高比时,可以使用wrap_content。
如果希望图片以特定的宽高比例显示,例如 2:1,可以在XML中指定:
fresco:viewAspectRatio="1.5"
四、Fresco VS Glide
1. 功能对比
要从功能上来说, fresco基本满足了所有的网络图片展示需求
2. 缓存对比
1). Fresco缓存
也是一大亮点, 三级缓存,分别是 Bitmap缓存,未解码图片缓存, 文件缓存。
这里提一点Bitmap缓存:在5.0以下系统,Bitmap缓存位于ashmem,这样Bitmap对象的创建和释放将不会引发GC,更少的GC会使你的APP运行得更加流畅。5.0及其以上系统,相比之下,内存管理有了很大改进,所以Bitmap缓存直接位于Java的heap上。
另外,磁盘缓存还可以通过代码来设置不同手机的缓存容量:
public void initFresco(Context context, String diskCacheUniqueName){
DiskCacheConfig diskCacheConfig = DiskCacheConfig.newBuilder(context)
.setMaxCacheSize(DISK_CACHE_SIZE_HIGH)
.setMaxCacheSizeOnLowDiskSpace(DISK_CACHE_SIZE_LOW)
.setMaxCacheSizeOnVeryLowDiskSpace(DISK_CACHE_SIZE_VERY_LOW)
.build();
ImagePipelineConfig config = ImagePipelineConfig.newBuilder(context)
.setMainDiskCacheConfig(diskCacheConfig)
.build();
Fresco.initialize(context, config);
}
2). Glide缓存
Glide虽然只有内存和磁盘缓存,在性能上比不上Fresco;但他也有另外的优点, Fresco缓存的时候,只会缓存原始图像,而Glide则会根据ImageView控件尺寸获得对应的大小的bitmap来展示,从而缓存也可以针对不同的对象:原始图像(source),结果图像(result); 可以通过.diskCacheStrategy()方法设置:
public enum DiskCacheStrategy {
/** Caches with both {@link #SOURCE} and {@link #RESULT}. */
ALL(true, true),
/** Saves no data to cache. */
NONE(false, false),
/** Saves just the original data to cache. */
SOURCE(true, false),
/** Saves the media item after all transformations to cache. */
RESULT(false, true);
}
3. bitmap操作
Glide与Picasso类似,通过简单的方法即可获得网络图片的bitmap对象:
Bitmap myBitmap = Glide.with(applicationContext)
.load(yourUrl)
.asBitmap() //必须
.centerCrop()
.into(500, 500)
.get()
相反,Fresco要获取bitmap更加复杂, 而且使用起来也并不是那么顺畅。首先,Fresco为了更好地管理bitmap 对象(bitmap对象申请和释放会引起频繁的GC操作,从而引起界面卡顿), 引入了可关闭的引用(CloseableReference), 持有者在离开作用域的时候需要关闭该引用,而我们要获取的bitmap 对象就是可关闭的引用。也就是说,我们不能像上面Glide那样把bitmap 对象取出来传递给其它地方使用, 只能在Fresco提供的作用域范围内使用,代码如下:
public void setDataSubscriber(Context context, Uri uri, int width, int height){
DataSubscriber dataSubscriber = new BaseDataSubscriber<CloseableReference<CloseableBitmap>>() {
@Override
public void onNewResultImpl(
DataSource<CloseableReference<CloseableBitmap>> dataSource) {
if (!dataSource.isFinished()) {
return;
}
CloseableReference<CloseableBitmap> imageReference = dataSource.getResult();
if (imageReference != null) {
final CloseableReference<CloseableBitmap> closeableReference = imageReference.clone();
try {
CloseableBitmap closeableBitmap = closeableReference.get();
Bitmap bitmap = closeableBitmap.getUnderlyingBitmap();
if(bitmap != null && !bitmap.isRecycled()) {
//you can use bitmap here
}
} finally {
imageReference.close();
closeableReference.close();
}
}
}
@Override
public void onFailureImpl(DataSource dataSource) {
Throwable throwable = dataSource.getFailureCause();
// handle failure
}
};
getBitmap(context, uri, width, height, dataSubscriber);
}
在实际使用过程中, 如果只有在作用域范围操作bitmap,明显不能满足需求。
项目中使用的方式是获取缓存的文件对象:
//同样在DataSubscriber中获取
FileBinaryResource resource = (FileBinaryResource) Fresco.getImagePipelineFactory().getMainFileCache().getResource(new SimpleCacheKey(url));
if (resource != null && resource.getFile() != null) {
setImage(ImageSource.uri(Uri.fromFile(resource.getFile())));
}
4. Fresco特有
除了以上内容,Fresco还具备以下一些常用的,但Glide没有的功能:
1,SimpleDraweeView控件可以指定图片的宽高比例(app:viewAspectRatio),对于手机适配非常重要;
2,图片加载进度;
3,先加载小尺寸图片,再加载大尺寸的(Glide只有占位图);
5. 性能对比
除了在功能上对比, 网络图片显示是非常耗性能的, 下面就针对图片质量,内存使用等情况来对比。
1). 图片显示质量
Glide的图片质量不如Fresco, 原因是Glide为了省内存, 采用了RGB_565的格式显示图片, 相对于”ARGB8888”要省了将近一半的内存。但也可以通过代码将图片格式改为ARGB_8888。
2). 加载图片速度
Fresco设计中有个有一个image pipeline模块, 可以最大限度节省网络下载图片, 在不考虑缓存的情况下, Fresco也比Glide快很多。 在demo中,同时加载上述图片, Fresco需要3s左右, Glide需要5s左右。
3). 内存使用情况
加载同一张图内存使用情况
情况1(控件比图片大)
情况2(控件比图片小)
当控件比较小的时候, Glide明显比情况1使用的内存少很多, 而Fresco则几户与情况1使用相同内存。因为Fresco在没有做过任何处理的情况下,会将原图片加入到内存中,然后做一些压缩处理显示在控件上; 而Glide则是直接准确获取了控件大小,然后得到一张与控件大小相当尺寸的图片,加载到内存并显示。
情况2当时在第一次引入Fresco的碰到过,有些高质量的图片显示在小尺寸的控件上,直接显示的话,很容易出现图片显示不出的情况。
Fresco也提供了方法将图片尺寸压缩,我们可以得到控件的宽高,然后进行压缩:
虽然可以解决内存溢出,不必要的内存消耗等情况,但是这样做的前提是必须提前知道控件的宽高,当图片控件使用了wrap_content等方式,这样做就会比较繁琐了。
而Glide则无需考虑这个问题。
4). 引申问题
Glide虽然在需要压缩问题上有优势,但也有另外一个问题, 缓存, 例如上述“情况2”加载了图片在小的控件上, Glide会将300*300的图片保存在缓存中,而当下次需要展现“情况1”(800x600)的时候, 会再次从网络中获取。
要解决这个问题, 需要另外进行缓存控制(参考上述 缓存):
.diskCacheStrategy(DiskCacheStrategy.ALL)
6. 总结
Fresco和Glide还有更强大的更灵活的功能,例如: Fresco可以自定义网络加载,与其它的Image Loader配合使用等等。
常用情况选择Glide. 选择的原因如下:
- Glide默认提供配置支持本地图片缓存,缓存的机制是DiskLruCache.可以根据自己的需要,自定义图片缓存的路径.所以在考虑节省用户流量来看可以不考虑Picasso;
- 虽然Fresco也提供更强大的图片缓存和加载机制,不过在比较之后,感觉Fresco还是有待完善.Glide可以很简单的获取网络图片的Bitmap对象,而Fresco需要通过订阅数据源克隆Bitmap对象的引用才能存储值.操作方式不够简洁和友好;
- Fresco的库文件中,以最新的0.8.1为例,imagepipeline-0.8.1.aar光包得大小就有3.5M而Glide包的大小为465K为了让Apk包得体积更小,所以考虑使用Glide。
五、写在最后
此文章为个人开发时记录,有时时间有限,无法深入研究,若看到此文章后有其他见解或解决方式,欢迎留言交流👇👇👇
参考链接:
https://www.dandelioncloud.cn/article/details/1548106913728442370
https://www.dandelioncloud.cn/article/details/1438138574574276609
————————————————
版权声明:转载请附上原文出处链接及本声明。
原文链接:
[https://blog.csdn.net/weixin_44158429/article/details/129842086]