glide之总结2

1、图片库对比

一. 如何缓存动态Url的图片?

 一般情况下我们从网络上获取到的图片Url都是静态的,即一张图片对应一个Url。那么如果是一张图片对应多个Url呢?缓存不就没有意义了。
因为图片加载库都是拿图片的Url来作为缓存的key的,Glide也不例外,只是会更加复杂一些。如果你开启了Glide的log,就会在控制台看到Glide是如何指定缓存key的。关于如何打开log,请参考这篇文章。
 一般来说,Glide的key由图片的url、view的宽和高、屏幕的尺寸大小和signature组成。在什么情况下才会出现动态的Url呢?
 一个很典型的例子就是因为图片的安全问题在原来图片的Url后面加上访问凭证。访问凭证与时间关联,这样一来,在不同时间同一图片的Url就会不同,缓存就会失效。以七牛的私有空间为例,我们来看看如何去缓存这类图片。从七牛关于私有空间的文档中可以得到:最终的Url = 原Url + ?e=过期时间 + token=下载凭证。

那么就只需要在Glide缓存时将Url中“?”后面的字符串截去就可以了。
首先新建一个叫做QiNiuImage的类:
public class QiNiuImage {
private final String imageUrl;
public QiNiuImage(String imageUrl) {
     this.imageUrl = imageUrl;
}
public String getImageUrl() {
    return imageUrl;
}
public String getImageId() {
 if (imageUrl.contains("?")) {
    return imageUrl.substring(0, imageUrl.lastIndexOf("?"));
 } else {
    return imageUrl;
}
}
}
其中getImageUrl方法返回真实的Url,getImageId方法返回未添加下载凭证前的Url。
然后再自定义一个实现ModelLoader接口的QiNiuImageLoader:
public class QiNiuImageLoader implements StreamModelLoader<QiNiuImage> {
@Override
public DataFetcher<InputStream> getResourceFetcher(final QiNiuImage model, int width, int height){
return new HttpUrlFetcher(new GlideUrl(model.getImageUrl())) {
@Override
public String getId() {
  return model.getImageId();}
};
}
public static class Factory implements ModelLoaderFactory<QiNiuImage, InputStream> {
@Override
public ModelLoader<QiNiuImage, InputStream> build(Context context,
GenericLoaderFactory factories) {
   return new QiNiuImageLoader();
}
@Override
public void teardown() { /* no op */ }
}
其中HttpUrlFetcher的getId方法就是组成缓存的key的重要部分。这也是我们的核心原理。
将这个ModelLoader注册到GlideModule中,并在AndroidManifest.xml中注册:
public class QiNiuModule implements GlideModule {
@Override
public void applyOptions(Context context, GlideBuilder builder) {

}
@Override
public void registerComponents(Context context, Glide glide) {
    glide.register(QiNiuImage.class, InputStream.class, new QiNiuImageLoader.Factory());
}
}
<meta-data
android:name="com.yourpackagename.QiNiuModule"
android:value="GlideModule"/>
最后只需要在加载此类图片时,使用下面这段代码就可以了。即使图片的token更换了也不会重新从网络上下载而是直接读取本地缓存。
Glide.with(context).load(new QiNiuImage(imageUrl).into(imageView);

二. 图片库对比

juejin.cn/post/684490…

 1) Glide Google 开源

支持 Gif WebP Video
生命周期继承
高效缓存策略
  • 支持Memory和Disk缓存
  • Picasso 只会缓存原始尺寸图片,而Glide缓存时多种规格
  • 内存开销小,默认 RGB_565,Picasso 默认是 ARGB_8888

缺点:

  • 使用方法复杂,实现方法较多
  • 使用比Fresco简单,但性能(加载&缓存)却比不上 Fresco

Picasso Glide Fresco比较?

2) Picasso 毕加索 Square

Picasso 没有实现本地缓存功能,交给了Square 的另外一个网络库okhttp去实现。
好处是可以通过请求 Response Header 中的 Cache-Control及Expired 控制图片的过期时间。
  • 使用简单,代码简洁
  • 与Square其他类库搭配兼容性好,Retrofit OkHttp 等

缺点:

  • 功能简单 图片加载
  • 性能(加载速度等等)较(Glide、Fresco)差
  • 自身没有实现"本地缓存"

3) Fresco Facebook

  • 大大减少OOM,底层使用C++技术解决图片缓存问题
  • 使用加单,几乎全部功能都能在 xml 上定制

缺点:

  • 用法变得更加复杂
  • 依赖包更大了 2~3M
  • 底层C++,阅读源码困难

juejin.cn/post/684490…

对比项PicassoGlideFresco
地址 github.com/square/pica… github.com/bumptech/gl… github.com/facebook/fr…
发布时间 2013年5月 2014年9月 2015年5月
是否支持gif false true true
是否支持webP true true true
视频缩略图 false true true
大小 100k 500 KB 2~3M
加载速度
Disk+Men Cache true true true
Easy of use low mediun difficult
star 13160 14709 12444
开发者 Square主导 Google主导 Facebook主导

详细属性对比

对比项GlideFresco
配置 compile 'com.github.bumptech.glide:glide:XXX.XXX' compile 'com.facebook.fresco:fresco:XXX.XXX
初始化 直接使用 Fresco.initialize(this);
layout 普通ImageView 独有的SimpleDraweeView
圆角, 圆形 需要自己实现圆角,继承自BitmapTransformation操作bitmap对象实现 通过RoundingParams设置参数
缓存 Glide内存和磁盘缓存 三级缓存,分别是 Bitmap缓存,未解码图片缓存, 文件缓存。
缓存图像大小 Glide则会根据ImageView控件尺寸获得对应的大小的bitmap来展示,从而缓存也可以针对不同的对象:原始图像(source),结果图像(result) 缓存原始图像
加载策略 Glide只有占位图 先加载小尺寸图片,再加载大尺寸的
加载进度 false true
Bitmap myBitmap = Glide.with(上下文)  
    .load(url)  
    .asBitmap() //必须    
    .get()
//同样在DataSubscriber中获取
FileBinaryResource resource = (FileBinaryResource) Fresco.getImagePipelineFactory().getMainFileCache().getResource(new SimpleCacheKey(url));
if (resource != null && resource.getFile() != null) {           
    setImage(ImageSource.uri(Uri.fromFile(resource.getFile())));
}

三. Fresco 源码分析

juejin.cn/post/684490…

初始化Fresco。
获取DataSource。
绑定Controller与Hierarchy。
从内存缓存/磁盘缓存/网络获取图片,并设置到对应的Drawable层。
 
缓冲缓存层:由BufferedDiskCache实现,提供缓冲功能。
文件缓存层:由DiskStorageCache实现,提供实际的缓存功能。
文件存储层:由DefaultDiskStorage实现,提供磁盘文件读写的功能。
DiskStorageCache:实现了FileCache接口与DiskTrimmable接口是缓存的主要实现类。
DefaultDiskStorage:实现了DiskStorage接口,封装了磁盘IO的读写逻辑。
BufferedDiskCache:在DiskStorageCache的基础上提供了Buffer功能。

private static final String CONTENT_FILE_EXTENSION = ".cnt"; private static final String TEMP_FILE_EXTENSION = ".tmp";

未解码图片内存缓存:由EncodedImage描述真正的缓存对象。 已解码图片内存缓存:由BitmapMemoryCache描述真正的缓存对象。

github.com/sucese/andr…

作者:爱雨浮龙
链接:https://juejin.cn/post/6844904005450104839

posted on 2020-03-21 21:55  左手指月  阅读(660)  评论(0编辑  收藏  举报