1.Glide是什么?
Glide是一个面向Android的快速高效的开源媒体管理和图像加载框架,它将媒体解码、内存和磁盘缓存以及资源池封装到一个简单易用的接口中;
Glide支持获取、解码和显示视频静像、图像和动画GIF。Glide包括一个灵活的API,允许开发人员插入几乎任何网络堆栈。默认情况下,Glide使用自定义的基于HttpUrlConnection的堆栈,但也包括插件到Google的Volley项目或Square的OkHttp库中的实用程序库。
Glide的主要重点是尽可能平滑和快速地滚动任何类型的图像列表,但Glide也适用于几乎任何需要获取、调整大小和显示远程图像的情况;
2.Glide依赖
在app_module下bulid.gradle添加glide依赖
dependencies {
?implementation 'com.github.bumptech.glide:glide:4.6.1'
annotationProcessor 'com.github.bumptech.glide:compiler:4.6.1'
}
3.Glide如何加载gif动画
//默认用glide加载本地或者网络gif图片
Glide.with(Context)
.asGif()
.load(res或者gif的url链接)
.into(ImageView);
3.1解决Glide加载gif非常慢的问题
添加缓存策略提高加载显示速度
RequestOptions options = new RequestOptions()
.fitCenter()
.diskCacheStrategy(DiskCacheStrategy.DATA);
Glide.with(context)
.asGif()
.load(res)
.apply(options)
.into(imageView);
为其添加缓存策略,其中缓存策略可以为:DATA及None,None及为不缓存,DATA缓存原型;推荐使用DATA在资源解码前缓存,保证图片不被压缩,此属性会导致第一次加载过慢,我的解决办法是做预加载;
Glide3.0和4.0的缓存策略DiskCacheStrategy区别
Glide3.0
????????????DiskCacheStrategy.NONE:不缓存 ?? ??? ??? ?DiskCacheStrategy.SOURCE:之缓存原图 ?? ??? ??? ?DiskCacheStrategy.RESULT:只缓存最终要显示的图片(默认选项; Picasso默认缓存原图) ?? ??? ??? ?DiskCacheStrategy.ALL:缓存所有版本的图片
Glide4.0
?? ??? ??? ?DiskCacheStrategy.ALL 使用DATA和RESOURCE缓存远程数据,仅使用RESOURCE来缓存本地数据; ?? ??? ??? ?DiskCacheStrategy.NONE 不使用磁盘缓存; ?? ??? ??? ?DiskCacheStrategy.DATA 在资源解码前就将原始数据写入磁盘缓存; ?? ??? ??? ?DiskCacheStrategy.RESOURCE 在资源解码后将数据写入磁盘缓存,即经过缩放等转换后的图片资源; ?? ??? ??? ?DiskCacheStrategy.AUTOMATIC 根据原始图片数据和资源编码策略来自动选择磁盘缓存策略。(默认策略)
3.2加载gif第一帧
RequestOptions options = new RequestOptions()
.fitCenter()
.diskCacheStrategy(DiskCacheStrategy.DATA);
Glide.with(context)
.asBitmap()????????//加载第一帧
.load(res)
.apply(options)
.into(imageView);
3.3控制播放次数
Glide3.0和4.0的播放gif区别
Glide3.0播放gif
Glide.with( this ).load(res或者url).diskCacheStrategy(DiskCacheStrategy.SOURCE).into( new ?GlideDrawableImageViewTarget(imageView,? 1 ));
Glide4.0播放gif
RequestOptions options = new RequestOptions()
.fitCenter()
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.DATA);
Glide.with(context)
.asGif()
.load(res)
.apply(options)
.listener(new RequestListener<GifDrawable>() {
@Override
public boolean onLoadFailed(GlideException e, Object model, Target<GifDrawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(GifDrawable resource, Object model, Target<GifDrawable> target, DataSource dataSource, boolean isFirstResource) {
//设置只播放一次
resource.setLoopCount(1);
return false;
}
})
.into(imageView);
}
3.5Glide加载Gif动画,切换页面的时候先显示最后一帧再开始播放动画的问题解决方案,设置Glide禁止使用内存缓存即可;
//禁止Glide缓存gif图片,否则会导致每次切换页面会先显示gif图片最后一帧,然后才开始播放动画
RequestOptions options = new RequestOptions() .skipMemoryCache(true);
3.6如何监听Glide播放gif完成
Glide3.0和4.0的播放gif完成监听区别
Glide3.0
Glide.with(this)
.load("xxxurl")
.listener(new RequestListener<Integer, GlideDrawable>() {
@Override
public boolean onException(Exception arg0, Integer arg1,
Target<GlideDrawable> arg2, boolean arg3) {
return false;
}
@Override
public boolean onResourceReady(GlideDrawable resource,
Integer model, Target<GlideDrawable> target,
boolean isFromMemoryCache, boolean isFirstResource) {
// 计算动画时长
GifDrawable drawable = (GifDrawable) resource;
GifDecoder decoder = drawable.getDecoder();
for (int i = 0; i < drawable.getFrameCount(); i++) {
duration += decoder.getDelay(i);
}
//发送延时消息,通知动画结束
handler.sendEmptyMessageDelayed(MESSAGE_SUCCESS,
duration);
return false;
}
}) //仅仅加载一次gif动画
.into(new GlideDrawableImageViewTarget(imageview, 1));
Glide4.0
但是在Glide4.0中,没法再直接获取GifDecoder 对象了,原因是因为GlideDrawable 不再提供这个方法了。 我这里是采用反射的方法获取到GifDecoder变量的,具体代码如下:
Glide.with(FirstActivity.this)
.asGif()
.load(file)
.fitCenter()
.diskCacheStrategy(DiskCacheStrategy.DATA)
.listener(new RequestListener<GifDrawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<GifDrawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(final GifDrawable resource, Object model, Target<GifDrawable> target, DataSource dataSource, boolean isFirstResource) {
new Thread(new Runnable() {
@Override
public void run() {
// 计算动画时长
int duration = 0;
try {
GifDrawable gifDrawable = (GifDrawable) resource;
//设置循环播放次数为1次
gifDrawable.setLoopCount(1);
//GifDecoder decoder = gifDrawable.getDecoder();//4.0开始没有这个方法了
Drawable.ConstantState state = gifDrawable.getConstantState();
if (state != null) {
//不能混淆GifFrameLoader和GifState类
Object gifFrameLoader = GlideGifUtil.getValue(state, "frameLoader");
if (gifFrameLoader != null) {
Object decoder = GlideGifUtil.getValue(gifFrameLoader, "gifDecoder");
if (decoder != null && decoder instanceof GifDecoder) {
for (int i = 0; i < gifDrawable.getFrameCount(); i++) {
duration += ((GifDecoder) decoder).getDelay(i);
}
//发送延时消息,通知动画结束
handler.sendEmptyMessageDelayed(MESSAGE_SUCCESS,
duration);
}
}
}
} catch (Throwable e) {
}
}
}).start();
return false;
}
})
.into(mAdImg);
反射工具类
public class GlideGifUtil {
/**
* 通过字段名从对象或对象的父类中得到字段的值
*
* @param object 对象实例
* @param fieldName 字段名
* @return 字段对应的值
* @throws Exception
*/
public static Object getValue(Object object, String fieldName) throws Exception {
if (object == null) {
return null;
}
if (TextUtils.isEmpty(fieldName)) {
return null;
}
Field field = null;
Class<?> clazz = object.getClass();
for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
try {
field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(object);
} catch (Exception e) {
//这里甚么都不要做!并且这里的异常必须这样写,不能抛出去。
//如果这里的异常打印或者往外抛,则就不会执行clazz = clazz.getSuperclass(),最后就不会进入到父类中了
}
}
return null;
}
}
同时,因为我们采用的是反射,所以别忘了在你的proguard-rules.pro 中加上Glide的反混淆规则;
#Glide
-keep class com.bumptech.glide.** {*;}
3.7如何提高一次加载Gif的速度
本地gif第一次提高加载速度,实际项目我采用的在导航页面提前通过glide加载gif图片,让glide控件完成gif图片的缓存,然后首页加载的时候glide加载的是缓存中的gif;
参考:
??????Android 进阶5:Glide4.0源码分析_lmq121210的博客-CSDN博客
Android使用Glide加载Gif慢 获取gif时间 - 唯爱~ - 博客园
Glide4.0只播放一次Gif以及监听播放完成的实现方法 - 简书
Gitee 极速下载/glide
|