Glide使用,踩过的坑

1.Glide特点

使用简单

可配置度高,自适应程度高

支持常见图片格式: Jpg png gif webp

支持多种数据源:  网络、本地、资源、Assets 等

高效缓存策略,支持Memory和Disk图片缓存默认Bitmap格式采用RGB_565内存使用至少减少一半

生命周期集成, 根据Activity/Fragment生命周期自动管理请求

高效处理Bitmap,使用Bitmap Pool使Bitmap复用,主动调用recycle回收需要回收的Bitmap,减小系统回收压力


2.Glide图片加载

1.支持文件、资源id、网络urigif加载。

2.待加载时显示,加载出错时显示

.placeholder( R.drawable.cupcake ).error( R.drawable.full_cake )

3.强制转化为gif

.asGif()

4.bitMap播放Gif,显示第一帧

.asBitmap()

5.动画效果

.crossFade()
淡入淡出动画的时间为300ms(毫秒),我们可以修改这个动画的时间
取消动画.dontAnimate()

6.添加头部信息

6.1 全局添加

利用GlideModule

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

Glide使用,踩过的坑_第1张图片



6.2 局部添加

Glide使用,踩过的坑_第2张图片


由于每个号码的头像头部信息都不一样,所以我们选择了局部添加。

Glide使用,踩过的坑_第3张图片


7. 设置图片大小和缩放形式

Glide 会根据ImageView的大小,自动限制图片缓存和内存中的大小,当然也可以通过调用override(horizontalSize,verticalSize)限制图片的大小:

Glide支持两种图片缩放形式,CenterCrop 和 FitCenter 

CenterCrop:等比例缩放图片,直到图片的狂高都大于等于ImageView的宽度,然后截取中间的显示。

FitCenter:等比例缩放图片,宽或者是高等于ImageView的宽或者是高。


8.圆形


.transform(new CircleTransform(mContext))

Glide使用,踩过的坑_第4张图片


9.缓存与失效机制signature


Glide提供了signature方法对图片进行标识,缓存图片有一个唯一的key,用于标识缓存图片是否是最新图片,是否需要刷新缓存。

Glide 通过 urlviewwidthviewheight、屏幕的分辨率等以一种散列算法生成一个独有、安全的文件名作为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, 自定义缓存


Glide使用,踩过的坑_第5张图片

然后将GlideModule加入AndroidManifest.xml文件中的meta-data标签,key是实现类的全限定名,valueGlideModule,如:




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使用,踩过的坑_第6张图片


不然会出现先显示别人头像,然后再显示自己头像。

 

快速滑动错位问题,如果跳过glide内存缓存的话,快读滑动列表则经常出现错位,目前使用了glide内存缓存和自定义内存缓存。

 

闪烁和错位问题网上很多解决方案,原因也很多,很多是在listview里面做一些设置,目前羽聊这种方法不需要再listview或者recycleview额外设置,在glidephoto接口已经做好了,其他模块不需要更改自身view。


你可能感兴趣的:(anroid)