深入理解Booster(二)-如何做png到webp的图片压缩

1,380 阅读5分钟

图片压缩的任务链

要找到是如何处理 图片压缩的,我们可以看下 接入booster以后 任务链上有什么变化

输入命令如下:

./gradlew :app:assembleDebug --dry-run

可以看出来 这里有installCwebpcomppressCwebp2个一看起来 就是图片压缩的自定义task

注意了它俩是插入到 mergeReleaseResources和packageDebugResources 2个任务中间的

image.png

同时我们也可以在build路径中 发现我们任务执行完毕以后的输出

image.png

task配置

先来看下 在config阶段 是如何把这2个任务 插入到 agp任务之间的

image.png

讲白了 在配置阶段 关键的函数 就是下面这个

image.png

可以来仔细分析下 执行过程:

18以下的手机 不支持alpha的webp,但是现在国内基本都是5.0以上了,所以我们直接看这个红框中的分支即可 image.png

主要关注下方2个红框中的逻辑:

image.png

先来看第一个红框 它在config阶段 做了什么事?

image.png

返回了一个command对象,这个对象 故名思议 看上去就是和命令行相关的,其实很好理解,因为最终压缩图片肯定是要调用一个cwebp的可执行文件的

我们可以具体把这个执行结果打印出来

image.png

这就是对应着我们具体的可执行文件的位置吧

继续查看下 我们的cwebp的插件,确实是内置了这些可执行文件 image.png

所以这里可以下第一个结论, 配置阶段 booster 获取到了自身的 可执行文件的 具体位置

再接着看:

image.png

从上图我们可以看出来 这里是返回了一个 SimpleCompressionTaskCreator的对象,注意这个对象的构建 涉及到2个参数

一个this 就是我们自己这个 CompressionTool

另外一个是一个lamda表达式,但是考虑我们只考虑兼容android5.0的情况 则 实际上就是

CwebpCompressOpaqueFlatImages

再回过去看一下:

本质上就是调用的 SimpleCompressionTaskCreator的 createCompressionTask 方法,注意这个方法 有6个参数

image.png

首先看一下这个函数返回的是一个TaskProvider类型,这个是啥意思?其实就代表只有在调用这个provider的get方法的时候 才会创建task 否则不创建,或者调用TaskCollection.getByName(java.lang.String)的时候也会创建对应的task

image.png

继续看,我们首先分析它的第一部分

image.png

image.png

这里其实就是为了保证 installCwebp 这个task 在mergeResources这个task之后执行

继续看:

image.png

这里我们先看第一个框,其实这个getCompressionTaskClass 就是前面 我们分析过的 CwebpCompressOpaqueFlatImages 也就是说 这个任务最终对应的task 就是它。

除此之外 我们看apply的lambda里面 代表啥? 代表着这个cwebp的任务 一定是在install这个任务之后。

同时 之前我们已经知道 install任务 在mergeRes这个任务之后,且这里还设置了 cwebp这个压缩任务在 processResTask 这个任务之前。 从而完整的构建出了 任务的可执行顺序

形如:

image.png

最后看下一个细节:

这个其实就是你要压缩图片 总要找到原图对吧,那这个supplier是啥?它其实就是某个参数

image.png

真正传递的参数就是它了 注意这个lambda里面的代码是要等到 执行期 才会被执行的(废话,config阶段 你根本拿不到前面编译的结果呀) image.png

任务执行期

前面我们分析好了 task的 顺序编排以后,剩下的其实就是分析task的执行过程,这个其实相对于前面的config阶段 倒是变的简单了

我们首先看第一部分:

image.png

这里其实就是因为googleplay 是拒绝 你的app icon为 非png格式的,所以我们在做png-webp 转换的时候 应该是 排除掉icon 只压缩转换非icon的 png 图片

所以上述的代码核心思想就是 通过manifest 文件的解析 来判断 到底哪些图片文件是用于appIcon的

然后继续看:

image.png

这里我们主要关注2点,

第一: 红框中的 images 其实你就可以理解为是获取mergeRes任务之后的输出 也就是那些经过aapt2 编译过的 png.flat 文件

有关于appt2 大家可以详细看下谷歌的这篇文档

aapt2

第二 就是aapt2ActionData 那段代码

这里其实就是做了两件事,做了2个命令的封装,

1个是 调用cwebp可执行文件去把我们的png文件 压缩成cwebp文件

2个是 将我们的cwebp文件 用aapt2 编译成 形如webp.flat 的文件 这一步非常重要,千万不要遗漏

最后看下实际的命令执行过程吧:

image.png

首先是真正的去执行 图片压缩

然后 根据图片压缩的结果来判断 是否要用aapt2 再次编译成.flat 文件

这里我们要关注一下细节,这里booster 不但判断了 压缩命令是否执行成功 还额外判断了压缩以后的图片和原文件的大小 做了比对,如果压缩以后 图片比之前还要大了 那就放弃这次压缩的结果 还用之前的

这个细节非常的妙(换我自己是写不出来的)