需求:

近段时间正好有一个需求,是要实现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. 快速入门函数式编程——以Javascript为例

    函数式编程是在不改变状态和数据的情况下使用表达式和函数来编写程序的一种编程范式.通过遵守这种范式,我们能够编写更清晰易懂.更能抵御bug的代码.这是通过避免使用流控制语句(for.while.brea ...

  2. Java标识符(Identifier)(关键字和保留字)

    Java标识符(Identifier) 1. 只能由英文字母(A~Z)或(a~z).下划线(_).美元符号($)和数字(0~9)组成,且开头不能为数字. 2. 区分大小写! 3. 无长度限制! _3_ ...

  3. Xcode 7中http通信出现如下错误

    Xcode 7中http通信出现如下错误:Application Transport Security has blocked a cleartext HTTP (http://) resource ...

  4. DBCP2的使用例子和源码详解(不包括JNDI和JTA支持的使用)

    目录 简介 使用例子 需求 工程环境 主要步骤 创建项目 引入依赖 编写jdbc.prperties 获取连接池和获取连接 编写测试类 配置文件详解 数据库连接参数 连接池数据基本参数 连接检查参数 ...

  5. 2019-2020-11 20199304 《Linux内核原理与分析》 第十二周作业

    ShellShock攻击实验 一.实验简介 2014年9月24日,Bash中发现了一个严重漏洞shellshock,该漏洞可用于许多系统,并且既可以远程也可以在本地触发 二.预备知识 1.shells ...

  6. Spring Cloud(二):Eureka 服务注册中心

    前言 服务治理 随着业务的发展,微服务应用也随之增加,这些服务的管理和治理会越来越难,并且集群规模.服务位置.服务命名都会发生变化,手动维护的方式极易发生错误或是命名冲突等问题.而服务治理正是为了解决 ...

  7. 点击按钮每次都能实现图片的旋转和切换(swift)

    效果如图: 代码如下: // // ViewController.swift // TwoSidedView // // Created by mayl on 2017/12/14. // Copyr ...

  8. [UWP]在应用退出时弹出确认提示框

    1. 需求 在应用退出时(点击右上角的关闭按钮)弹出一个确认按钮可以说是一个最常见的操作了,例如记事本的"你是否保存": 但这个功能在UWP上居然有点小复杂.这篇文章将解释如何实现 ...

  9. 关于SQL Server 中日期格式化若干问题

    select CONVERT(varchar, getdate(), 120 )2004-09-12 11:06:08 select replace(replace(replace(CONVERT(v ...

  10. luogu P1908 逆序对 |树状数组

    题目描述 猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计.最近,TOM老猫查阅到一个人类称之为"逆序对"的 ...