背景
现在很多app都会使用大量的动图资源来提升用户体验,而一般动图他们都会选用Gif图片格式,但是Gif图片格式存在一些不能忽视的问题
- 文件体积大:同等视觉效果下,GIF 体积会比其他动图格式大个3-5倍
- 色彩限制:仅支持 256 色,视觉表现力差
- 无 Alpha 通道:不支持透明背景,难以叠加在 UI 上层
- 解码性能差:逐帧解码,内存占用高
随着这些问题的暴露,越来越多的团队开始将动图格式转向了webp,这个图片格式是由谷歌推出的,它有如下优点
- 有损/无损压缩:相比png减少26%体积,相比jpeg减少 25%~34%
- 动图支持:支持动画帧序列,帧间差异编码进一步减小体积(webp比gif低64%)
- 透明通道:支持Alpha通道,完美适配UI叠加场景
- 更快的解码速度:webp解码器性能优于gif解码器
鉴于目前Android项目的主流图片加载框架要么是Glide,要么就是Coil,所以接下去我们要讨论的是这两个图片框架如何去加载webp动图
Glide
Glide虽然依靠它的链式调用,加载一张图片很简单,但是试过的人会知道,如果拿一个webp动图用Glide去load的话,会发现动图并没有动起来,仅仅只是展示的是一张静态图,那是因为Glide本身只内置了webp静态图解码器,并没有内置webp动图解码器,动图相关的只内置了gif动图解码器GifDecoder,而如果想要让Glide支持展示webp动图的话,就必须通过三方扩展库来解决
webpdecoder 库的工作原理
我们通过引入com.github.zjupire:webpdecoder三方库来解决webp动图展示问题,这个三方库是Glide一个扩展库,它通过Glide的注解处理器机制自动注册组件

其中 WebpDrawableTransformation 是其关键设计

它通过将 BitmapTransformation 代理给 WebpDrawable 内部的每一帧,实现了转换的透传:外部看起来是给 WebpDrawable 注册了一个转换器,实际上这个转换器内部对每一帧 Bitmap 应用了原始的 BitmapTransformation
依赖引入

这里的版本号选取跟其他库不一样,不一定要用最新的,得根据你项目中使用的Glide版本来匹配,由于当前项目使用的Glide版本是4.13.2,所以webpdecoder的版本号这里选择的是2.1.4.13.2,可以从这个链接中查看具体webpdecoder都有哪些版本
自定义请求参数GlobalRequestOptions
GlobalRequestOptions 是整个方案的关键,它确保所有 BitmapTransformation 都能正确应用于 WebpDrawable

外部调用
可以提供统一webp图片加载入口,内部使用GlobalRequestOptions作为核心加载模块

验证结果
让AI帮忙生成一张webp动图,并且启动本地http server,使用上述方式加载本地这张webp动图链接,最终看到webp动图成功加载在来界面上

Coil
Coil目前国内普及度也蛮高了,而且在加载图片上,它甚至比Glide还要容易,使用它内置的load扩展函数就能完成一张图片的加载

那么Coil能不能加载webp动图呢,下面来试一下
导入核心库
使用Coil加载图片,先要将Coil导入到项目,这里选用的Coil的版本是2.6.0

使用load函数加载图片
在上述Glide加载图片的位置,我们替换成Coil去加载

但是悲催的发现,加载出来的却只是一张静态图

导入coil-gif支持动图
其实原因跟Glide比较相似,我们刚才导入的只是coil的核心库,只有coil-base,它里面只有一个BitmapFactoryDecoder,处理静态图的

所以解决办法就是额外再增加coil-gif依赖

初始化动图解码器
导入好了coil-gif之后,需要初始化动图解码器,我们在Application中添加如下初始化代码

现在就可以顺利将webp动图成功加载出来了
最后
希望对你有帮助,拜拜