需求:

近段时间正好有一个需求,是要实现Gif图只加载播放一次,并且要在Gif播放完毕后回调给系统的需求。

因为Glide 3系列的API与4系列还是有很大差距的,这里我们针对Glide 3.x和Glide 4.x的分别进行实现方案的说明。

解决方案:

在Glide3.x的解决方案:

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));

在Glide3.x的解决方案:

在Glide4.x中,我们没法再直接获取GifDecoder对象了,原因是因为GlideDrawable不再提供这个方法了。需要采用反射的方法获取到GifDecoder变量,具体代码如下:

public static void loadOneTimeGif(Context context, Object model, final ImageView imageView, final GifListener gifListener) {
Glide.with(context).asGif().load(model).listener(new RequestListener<GifDrawable>() {
@Override
public boolean onLoadFailed(@Nullable 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) {
try {
Field gifStateField = GifDrawable.class.getDeclaredField("state");
gifStateField.setAccessible(true);
Class gifStateClass = Class.forName("com.bumptech.glide.load.resource.gif.GifDrawable$GifState");
Field gifFrameLoaderField = gifStateClass.getDeclaredField("frameLoader");
gifFrameLoaderField.setAccessible(true);
Class gifFrameLoaderClass = Class.forName("com.bumptech.glide.load.resource.gif.GifFrameLoader");
Field gifDecoderField = gifFrameLoaderClass.getDeclaredField("gifDecoder");
gifDecoderField.setAccessible(true);
Class gifDecoderClass = Class.forName("com.bumptech.glide.gifdecoder.GifDecoder");
Object gifDecoder = gifDecoderField.get(gifFrameLoaderField.get(gifStateField.get(resource)));
Method getDelayMethod = gifDecoderClass.getDeclaredMethod("getDelay", int.class);
getDelayMethod.setAccessible(true);
//设置只播放一次
resource.setLoopCount(1);
//获得总帧数
int count = resource.getFrameCount();
int delay = 0;
for (int i = 0; i < count; i++) {
//计算每一帧所需要的时间进行累加
delay += (int) getDelayMethod.invoke(gifDecoder, i);
}
imageView.postDelayed(new Runnable() {
@Override
public void run() {
if (gifListener != null) {
gifListener.gifPlayComplete();
}
}
}, delay);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return false;
}
}).into(imageView);
} /**
* Gif播放完毕回调
*/
public interface GifListener {
void gifPlayComplete();
}

同时,因为采用的是反射,所以别忘了proguard-rules.pro中加上Glide的反混淆规则:

#Glide
-keep class com.bumptech.glide.** {*;}

Glide只播放一次Gif以及监听播放完成的实现方案的更多相关文章

  1. IOS使用AVAudioPlayer播放mp3歌曲文件并监听来电打断

    本实例实现了AVAudioPlayer播放mp3歌曲文件,实现了播放.暂停.继续操作,音乐音量控制.播放进度显示,同时监听来电打断事件 一.控件初始化 - (void)viewDidLoad { [s ...

  2. html5 video 监听播放结束. 最好获取html标签而不是id。

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. 监听auduo标签播放

    <audio id="audio" controls="controls" loop="loop" style="displ ...

  4. js监听audio播放完毕

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  5. Android如何监听蓝牙耳机的按键事件

    写在前面: 直接想要代码很简单,你直接把滚动条拉到最底端就可以看到.如果想要十分地了解为什么,那就按照我规划的一步一步来理解.以下测试环境以手头上有的「Bluedio + 红米手机」. 1.蓝牙耳机的 ...

  6. Android如何监听蓝牙耳机的按键事件(转)

    源: Android如何监听蓝牙耳机的按键事件 写在前面: 直接想要代码很简单,你直接把滚动条拉到最底端就可以看到.如果想要十分地了解为什么,那就按照我规划的一步一步来理解.以下测试环境以手头上有的「 ...

  7. Android怎样监听蓝牙耳机的按键事件

    Android怎样监听蓝牙耳机的按键事件 写在前面: 直接想要代码非常easy,你直接把滚动栏拉到最底端就能够看到.假设想要十分地了解为什么,那就依照我规划的一步一步来理解.下面測试环境以手头上有的「 ...

  8. ORACLE清理、截断监听日志文件(listener.log)

    在ORACLE数据库中,如果不对监听日志文件(listener.log)进行截断,那么监听日志文件(listener.log)会变得越来越大,想必不少人听说过关于"LISTENER.LOG日 ...

  9. 配置静态监听解决ORA-12514错误的案例(转)

    今天做Linux下DG配置的时候,遇到一个现象,tnsname.ora文件配置都正常,tnsping也正常,监听也正常,但是仍然报ORA-12514错误:   SQL> set lin 130 ...

随机推荐

  1. python中将xml格式转json格式

    一.简介 在用python写脚本时,通常需要处理xml格式的文件或字符串.由于json格式处理的方便性, 我们可将其转为json格式进行处理. 二.步骤 1.安装工具包xmltodict 在命令行输入 ...

  2. selenium webdriver学习--------iframe的处理

    有时候我们在定位一个页面元素的时候发现一直定位不了,反复检查自己写的定位器没有任何问题,代 码也没有任何问题.这时你就要看一下这个页面元素是否在一个iframe中,这可能就是找不到的原因之一.如果你在 ...

  3. scrapy项目部署

    什么是scrapyd Scrapyd是部署和运行Scrapy.spider的应用程序.它使您能够使用JSON API部署(上传)您的项目并控制其spider. 特点: 可以避免爬虫源码被看到. 有版本 ...

  4. idea为什么maven工具栏下面没有dependencies跟Plugins

    刚刚新建的springboot项目,然后进来就是这样子 网上查找资料有些说是maven版本的问题,但是对于我的问题并没有得到解决. 现在是2019年12月4日16:23:07,依然没有找到解决方法,不 ...

  5. 深入浅出Spring(一)

    现在很多的企业级项目中基本上都会用到了Spring框架,那么为什么会出现Spring,Spring是什么?这次的博文我主要为大家简单介绍一下Spring. Java EE优缺点 我们都知道在2003年 ...

  6. 对照谈-官方spring-boot-starter和自定义starter异同分析

    在前面我讲用spring-boot-starter-mail发邮件的时候,我侧重看的是spring boot发邮件的便利性,今天,我们聊下另外一个方面,spring-boot-starter自身的结构 ...

  7. Docker虚拟化之<基础理论>

    1.虚拟化技术的概念 (1)虚拟化技术主要是将物理的资源转变为逻辑上可以管理的资源,以打破物理结构上的壁垒,让计算元件运行在虚拟的基础上,而不是真实的物理资源上.(2)虚拟化技术的底层是要进行虚拟化的 ...

  8. java.lang.ClassNotFoundException: com.demo.search.extractAbstract.service.ExtractAbstractServiceHandler

    在利用 Spring 对 thrift 进行集成时,出现错误: avax.servlet.ServletException: Servlet.init() for servlet search-nlp ...

  9. Java修炼——容器HashMap用法

    直接上代码,容器集合之间的关系在后面我会继续详细分析,这次先看HashMap用法 HashMap的方法都在代码中有解释.有需要的可以仔细看看 package com.bjsxt.map; import ...

  10. Nginx(http协议代理 搭建虚拟主机 服务的反向代理 在反向代理中配置集群的负载均衡)

    Nginx 简介 Nginx (engine x) 是一个高性能的 HTTP 和反向代理服务.Nginx 是由伊戈尔·赛索耶夫为俄罗斯访问量第二的 Rambler.ru 站点(俄文:Рамблер)开 ...