一名优秀的 Android 开发, 需要一份完备的 知识体系, 在这里, 让我们一起成长为自己所想的那样~.
/ 开胃菜 /
在讲之前, 我们先补充一点基础知识, 安卓 ImageView 支不支持加载 Gif 动图呢? 其实是不支持的, 因为 ImageView 本身就是一个 View,View 的绘制需要用 Canvas, 而 Canvas 只支持 canvas.drawBitmap, 也就是同一时间只能绘制一张位图, 而 Gif 是由多帧图片组成, 那么 Glide 是如何让 ImageView 实现播放 Gif 动图呢?
还是从 Glide 给我们提供的写法来入手这块的源码
一上来就发现了今天的主角: GifDrawable
确认过眼神, 是想要的类
那么问题来了, 这个类有将近 500 多行代码, 我们该从哪里看起?
这就跟看书类似, 我们可以先看目录, 在源码中也差不多, 只不过它叫代码结构
/ 源码解析 /
通过查看代码结构, 我们发现了一个方法, 从方法名上理解, 它是开始播放第一帧的方法, 那么我们就从这个方法入手
我们可以看到当 Gif 只有一帧的时候, 会直接调用绘制方法, 而 Gif 不止一帧的时候, 那么它就开启了订阅, 接下来让我们看看这个订阅的方法里面做了什么事情
接下来让我们重点看一下这三句代码分别做了什么事
看到这里我们大概明白了, 这个方法是用来递增帧位置的, 从它的算法来看, 这还是一个无限轮播的算法
看完了 advance 的作用, 我们回去接着看剩下的两句代码
是不是忽然有点蒙, 这个类是什么, 我们先看一下它的父类
是不是有点似曾相识, 但就是怎么也说不出来什么, 让我们先看看它的父类
这个 Target 就是我们上篇讲到图片加载流程提到过的接口
这个接口的作用就是回调一些加载监听, 这个接口前面三个方法分别是: 加载开始, 加载失败, 加载成功读取资源的回调
现在我们知道了这个是加载资源的回调, 那么它又是从哪里调用的?
就是在我们后面要讲的第三句代码里面调用的, 真是让人意想不到
我们看到在加载资源的回调中发送了一个消息, 那么这个消息最终是去了哪里, 接下来让我们根据这个消息的 what 参数进行跟踪
看到 handleMessage 忽然有了一种熟悉的味道, 我们看到这里主要处理了两种消息, 一种是延迟消息, 一种是清理消息. 接下来让我们先看看, 如果这是一个延迟消息会发生什么事
在这里我们看到, 它会先获取当前帧数据, 然后再通过 Canvas.drawBitmap 到 ImageView 上面, 接下来我们回去刚刚那个方法里面, 看看它还做了些什么
原来如此, 它在刷新新的一帧数据到 ImageView 之后, 会对旧的一帧数据进行清除
然后再回去继续看, 它还做了什么事
还是原来的方法, 还是熟悉的三句代码
/ 总结 /
Glide 加载 Gif 的原理比较简单, 就是将 Gif 解码成多张图片进行无限轮播, 每帧切换都是一次图片加载请求, 再加载到新的一帧数据之后会对旧的一帧数据进行清除, 然后再继续下一帧数据的加载请求, 以此类推, 使用 Handler 发送消息实现循环播放.
来源: http://www.jianshu.com/p/25ae820eccd7