深入理解Booster(一)-gradle插件开发如何兼容不同的agp版本

想对gradle插件编写有深入了解的可以具体看下这个开源库booster

森哥的作品 你值得拥有。

这里就是逐步分析下booster的技术细节,学习他的代码和设计理念,方便我们自身以后编写插件。

我之前编写插件的时候 感到很痛苦的一个事情就是 我的代码只能兼容一个宿主的agp版本,比如目前我自己的项目agp版本是 4.1, 如果agp升级到7.0版本 一些agp的接口发生了变化,那么我就不得不 去修改我的代码来适配新的agp版本,这会导致 我新修改的插件版本 将不能适配老的项目结构。

而booster 则可以轻而易举的做到适配所有版本的agp ,我们来看看booster是如何做到的

booster的基础架构

首先这里要说明一个booster的基础理念,就是依赖反转 以及对应的spi技术 这里不去具体讲解这俩技术了,大家网上搜搜一堆教程 不难理解。重点说下 booster 为什么会做这个设计

众所周知Booster有很多功能,如果把这些功能都集成到booster的基础配置中,这个插件会非常庞大,因为确实有很多人只需求那么1-2个功能。

所以这里森哥将spi技术用到了极致,booster的基础功能

booster-gradle-plugin

image.png

只是提供了一个运行时的容器,具体你哪要使用哪个功能 你再额外添加那个功能专属的插件jar 即可。这样容器在运行时会动态加载你配置好的插件,这样一来 就可以分离 所谓 容器具体的功能插件

所有的插件其实入口都是要继承这个接口的

image.png

image.png

我们可以看下有多少个类继承了他

image.png

每一个类其实就是一个具体的功能插件的task 入口。

我们以图片压缩为例:

image.png

注意看 这里有一个 autoService的注解

image.png

这个库就是谷歌出的一个方便我们使用spi的库,有了它,我们只要注解一下 就可以自动帮我们在classpath中 生成 对应的 META-INF 配置文件了,否则我们要一个个手写 很容易出错

插件的版本兼容

有了前面的基础 我们再来看看 插件是如何做版本兼容的

首先booster-gradle-plugin 是包含了我们这个 booster-android-gradle-api

image.png

看依赖关系可以看出来 有很多工程的名字就是在告诉你 我对插件的版本做了兼容

再看booster-android-gradle-compat 这个基础工程

image.png

他其实就是定义了2个接口,我们只要按照这个接口去实现我们对应的版本适配即可

重点看下APIInterface这个类 你看它规定了这么多对外暴露的api我们 实际编写插件的人就调用接口方法就可以了 具体是哪个imple 来做对应的实现 则交给其他地方决定。 这里就是针对接口编程的最佳实践

image.png

根据宿主情况选择最佳的APIInterface实现类

回到插件执行的入口处

image.png

重点就是在这里了:

image.png

image.png

重中之重就是在下面的代码了: image.png

AGP这个对象在初始化的时候 首先会触发FACTORIES这个初始化,它的FACTORIES初始化 就是spi的过程 我们注意看它其实就是在找APIInterface到底有几个实现,然后转成一个list 供后面选择

Version.ANDROID_GRADLE_PLUGIN_VERSION
复制代码

这个其实就可以打印出我们当前的agp版本的,比如我demo工程里是7.1.2 那么这里 返回的值就是7.1.2 我们把它解析成Revision以后 就可以在刚才的list 中选择一个合适的APIInterface对象了

注意最终其实通过factory.newAPInterface 来实例化的

简易版的 agp兼容怎么做?

看了booster的代码以后 其实我们就大概能理清楚如何做agp版本兼容了,如果做的简单一点就是定义一堆接口 接口返回你要做的事情,然后根据版本来写对应的实现类

不用spi的话,我们就可以直接在插件的入口处写一个when语句 判断下Version.ANDROID_GRADLE_PLUGIN_VERSION的版本 然后直接new出来我们对应的实现就可以了 有人可能要问 这个简单的方案 为啥booster没用呢,

因为如果用spi的方案,则版本判断那里 不用再改代码了,每次新的agp版本到来 我们只要适配新的就可以了。 而如果用我们这个简单的方案,每次新版本到来 我们是不是还需要在when语句中修改一下对应的实现呢?

Guess you like

Origin juejin.im/post/7075602601034645541