1.Glide特点
使用简单
可配置度高,自适应程度高
支持常见图片格式: Jpg png gif webp
支持多种数据源: 网络、本地、资源、Assets 等
高效缓存策略,支持Memory和Disk图片缓存默认Bitmap格式采用RGB_565内存使用至少减少一半
生命周期集成, 根据Activity/Fragment生命周期自动管理请求
高效处理Bitmap,使用Bitmap Pool使Bitmap复用,主动调用recycle回收需要回收的Bitmap,减小系统回收压力
2.Glide图片加载
1.支持文件、资源id、网络uri、gif加载。
2.待加载时显示,加载出错时显示
.placeholder(
R.drawable.cupcake)
.error(
R.drawable.full_cake)
3.强制转化为gif
.asGif()
4.用bitMap播放Gif,显示第一帧
.asBitmap()
5.动画效果
.crossFade()
淡入淡出动画的时间为300ms(毫秒),我们可以修改这个动画的时间
取消动画.dontAnimate()
6.添加头部信息
6.1 全局添加
publicclassMyGlideModuleimplementsGlideModule {
@Overridepublicvoid applyOptions(Context context,GlideBuilder builder) {
// Apply options to the builder here.
}
@Overridepublicvoid registerComponents(Context context,Glide glide) {
// register ModelLoaders here.
}
}
继承BaseGlideUrlLoader写一个自己Loader,重载里面的getHeaders
6.2 局部添加
由于每个号码的头像头部信息都不一样,所以我们选择了局部添加。
7. 设置图片大小和缩放形式
Glide 会根据ImageView的大小,自动限制图片缓存和内存中的大小,当然也可以通过调用override(horizontalSize,verticalSize)限制图片的大小:
Glide支持两种图片缩放形式,CenterCrop 和 FitCenter
CenterCrop:等比例缩放图片,直到图片的狂高都大于等于ImageView的宽度,然后截取中间的显示。
FitCenter:等比例缩放图片,宽或者是高等于ImageView的宽或者是高。
8.圆形
.transform(new CircleTransform(mContext))
9.缓存与失效机制signature
Glide提供了signature方法对图片进行标识,缓存图片有一个唯一的key,用于标识缓存图片是否是最新图片,是否需要刷新缓存。
Glide 通过 url、viewwidth、viewheight、屏幕的分辨率等以一种散列算法生成一个独有、安全的文件名作为key保存到disk上.因为其是通过一个散列算法来实现的,因此很难定位文件的缓存,幸好Glide提供了signature()方法允许将一个附加的数据加入到缓存key当中,可以用来保证缓存的及时性.
builder.signature(new StringSignature(etag));
app首页中4个fragment中头像是使用缓存加载,当某个联系人头像更改了,由于url没有变化,会从缓存加载头像,导致永远显示旧头像,因此需要通过signature来标识头像的变化,从而从网络加载头像并且刷新缓存。
使用builder.signature(new StringSignature(etag));,当etag和缓存头像的当前key不一致时,即使采用了缓存策略,也会从网络下载头像,然后刷新缓存,使当前缓存的key为etag。下次再加载该头像,由于etag和当前缓存头像的key一致,走正常缓存策略。
那头像刷新了怎么来通知etag需要变化呢,设定在详情页,头像接口为先从缓存读取,然后再跳缓存读取网络图片,假如头像已经更改了,则会先显示原来头像,然后再显示最新头像,读取最新头像成功后,更新etag,存到本地磁盘,文件内容为一段数字,类似于时间戳,注意这时只是更新了本地etag文件,最新图片还没有存到本地缓存,回到fragment,重新加载图片,通过signature判断了最新的etag和本地缓存头像的key不一致,则从网络下载头像并刷新缓存,这时最新图片才会更新到本地缓存里。
app头像加载有2个接口:
1. 缓存策略
loadPhoto(this, mPicture, phoneNum);
2.跳缓存加载网络图片
loadProfilePhotoFromNet(this,mPicture, phoneNum, true);
App启动的4个fragment以及各列表中的头像应采取缓存策略,进入到个人详情页面采用跳缓存加载网络图片策略,若头像变化了则通知etag改变。
10.GlideModule, 自定义缓存
然后将GlideModule加入AndroidManifest.xml文件中的meta-data标签,key是实现类的全限定名,value是GlideModule,如:
11.缓存策略
设置跳过内存缓存
Glide.with(this).load(imageUrl).skipMemoryCache(true).into(imageView);
设置磁盘缓存策略
Glide.with(this).load(imageUrl).diskCacheStrategy(DiskCacheStrategy.ALL).into(imageView);
策略解说:
all:缓存源资源和转换后的资源
none:不作任何磁盘缓存
source:缓存源资源
result:缓存转换后的资源
缓存的动态清理
Glide.get(this).clearDiskCache();//清理磁盘缓存需要在子线程中执行
Glide.get(this).clearMemory();//清理内存缓存 可以在UI主线程中进行
12APP中glide头像加载踩过的坑
1. token获取不及时
由于token获取较慢,当token为空,会先从缓存获取图片,然后保存该号码到查询队列,收到用户成功登陆的广播后,获取最新token,加载队列中的号码,获取号码最新的图片。
1. 闪烁
ListView、RecyclerView列表滑动导致图片错位、闪烁问题。
原因:View的复用,图片异步加载。 比如ListView上有100个Item,一屏只显示10个Item,我们知道getView()中convertView是用来复用View对象的,因为一个Item的对应一个View对象,而ImageView控件就是View对象通过findViewById()获得的,而我们在复用View对象时,同时这个ImageView对象也被复用了。比如第11个Item的View复用了第1个Item View对象,那么ImageView就同时被复用了,所以当图片没下载出来,这个ImageView(第11个Item)显示的数据就是复用(第1个Item)的数据。
先读内存缓存,若没有则设置占位图,读磁盘缓存,若没有读网络图片,然后更新内存缓存和磁盘缓存。
Glide的闪烁是读取磁盘缓存或者网络加载导致。
发现有时没有走内存缓存,估计被回收了,这时就会从磁盘读取,导致闪烁。
设置一个内存缓存。
如果走glide内存缓存,则不会执行onLoadStarted函数,当glide内存缓存失效,在onLoadStarted里搜索自定义的内存缓存,搜索到显示缓存头像,否则显示默认头像(占位图),防止错位。
当读取磁盘缓存或者网络头像,会添加到自定义的内存缓存中。
addContactPhotoToCache(phone,resource);
1. 错位
由于listview复用机制,会复用imageview,所以要在加载磁盘图片或者网络图片等耗时操作时,必须预先设置图片。
不然会出现先显示别人头像,然后再显示自己头像。
快速滑动错位问题,如果跳过glide内存缓存的话,快读滑动列表则经常出现错位,目前使用了glide内存缓存和自定义内存缓存。
闪烁和错位问题网上很多解决方案,原因也很多,很多是在listview里面做一些设置,目前羽聊这种方法不需要再listview或者recycleview额外设置,在glidephoto接口已经做好了,其他模块不需要更改自身view。