android-gif-drawable 加载 Gif图片的 细节分析

Gif 加载对比

android-gif-drawable 来加载gif 和glide 对比一下

注意这里的GifDrawable 和 glide里面的不是一个

kotlin 复制代码
Thread() {  
run {  
var futureTarget: FutureTarget<File?>? = Glide.with(this)  
.downloadOnly()  
.load(url)  
.submit() // 一次性加载了 整个gif 图片的大小  
val drawable = GifDrawable(futureTarget?.get()!!.path)  
runOnUiThread {  
imageview.setImageDrawable(drawable)  
}  
}  
}.start()

加载gif 时的性能对比可以看出来整体加载曲线很平稳,且内存占用只有62.8mb

可以看下具体的内存占用分布

再来看看原生glide 加载 gif的 场景:

可以看出来 使用glide 原生加载gif的时候 峰值内存达到175mb

平稳以后也有 接近115mb的内存占用

加载流程

可以看出来这个Drawable的构造方式有很多

我们一般都是传一个固定file path进去,

可以看出来 在构建Drawable的过程中,会调用一个c++方法 去打开这个文件

这个jni 方法 主要就是 返回一个GifInfo对象的指针地址

在我们对imageview 调用了setImageViewDrawable方法以后, 其实会有一系列的回调到我们的drawable中

其中最重要的就是draw 和invalidateself 2个方法

扯远了, 我们回到之前的 GifDrawble 构造方法中来

doWork 我们最关注的 就是 红框中的2个步骤

第一个就是renderFrame

最后调用的是这个jni方法,参数其实就是一个空的bitmap

这个jni方法做的就是把这个bitmap的像素值 按照gif里的帧 给她填满

所以看到这 大家应该有一个感受了, 如果你是在主线程中创建的GifDrawable 那么至少会有两次 耗时操作

一个是读取文件,另外一个就是这里的绘制bitmap中的像素,

**所以我们在用这个gif库的时候 条件允许 可以在子线程去创建GifDrawable **

逐帧播放的逻辑

前文我们跟到了手动调用doWork的逻辑,在GifDrawable 构造函数 中,doWork 除了 解析出 gif的第一帧以外,还发送了一个handler 消息 我们可以跟一下这个handler 消息做了啥

可以看出来 最终还是 将renderTask 放到 一个线程池中去执行了,也就是说 对于这个Gif库来说,从Gif的第二帧 开始 他都是100% 在子线程在做的 帧解析

另外我们也可以看到 相比于Glide,这个库的优点,这个库甚至都没有使用BitmapPool,全程就只有构造函数中 createBitmap 一处调用,所谓的逐帧播放 都是对这个bitmap 内存的反复擦写罢了。

相比于Glide,不但 少了一个GIF本身的文件内存, 甚至 bitmap 对象池都省略了。

相关推荐
fatiaozhang95271 小时前
中兴B860AV5.2-U_原机安卓4.4.2系统专用_晶晨S905L3SB处理器_线刷固件包
android·电视盒子·刷机固件·机顶盒刷机·中兴b860av5.2-u
儿歌八万首1 小时前
Android 自定义 View 实战:打造一个跟随滑动的丝滑指示器
android·kotlin
我有与与症1 小时前
Kuikly 实战:手把手撸一个跨平台 AI 聊天助手 (ChatDemo)
android
恋猫de小郭1 小时前
Flutter UI 设计库解耦重构进度,官方解答未来如何适配
android·前端·flutter
apihz2 小时前
全球IP归属地查询免费API详细指南
android·服务器·网络·网络协议·tcp/ip
hgz07103 小时前
Linux环境下MySQL 5.7安装与配置完全指南
android·adb
Just_Paranoid3 小时前
【Android UI】Android 添加圆角背景和点击效果
android·ui·shape·button·textview·ripple
梁同学与Android3 小时前
Android ---【经验篇】阿里云 CentOS 服务器环境搭建 + SpringBoot项目部署(二)
android·spring boot·后端
风往哪边走3 小时前
自定义简易日历
android