使用Transform
的常见场景有埋点统计、耗时监控、方法替换
通过上图以我们了解下transform的作用,transform
在 class 到 dex 之间工作,处理包括 javac 编译后的字节码文件,每个 transform 都对应一个 Task,transform 的输入和输出对应 transform task 的输入输出。每个 transform task 的输出都分别存储在app\build\intermediates\transform\[Transform Name]\[Variant]
下
1. transform 方法
Transfom 的几个核心API可以查看 buildSrc方式 - transform 下的介绍,这里我们着重挑 transform 方法做下介绍
@Override
void transform(TransformInvocation transformInvocation) throws TransformException, InterruptedException, IOException {
super.transform(transformInvocation)
println '转换开始........................'
def start = System.currentTimeMillis()
def inputs = transformInvocation.inputs
def outputProvider = transformInvocation.outputProvider
if (outputProvider != null)
outputProvider.deleteAll()
// transform 的 inputs 有两种类型:一种是目录,一种是jar包
inputs.each { input ->
// 本地 project 编译成的多个 class 文件存放的目录
input.directoryInputs.each { dir ->
handleDirectory(dir,outputProvider)
}
// 各依赖锁编译成的 jar 文件
input.jarInputs.each { jar ->
handleJar(jar, outputProvider)
}
}
def cost = (System.currentTimeMillis() - start) / 1000
println "转换结束............................:$cost"
}
- getInputs:获取 TransformInput 对象,它是消费型输入内容,对应 getScopes() 定义的范围,transformInput 由两部分组成
- DirectoryInput 集合:以源码方式参与构建的输入文件,包括完整的源码目录结构及其中的源码文件
- JarInput集合:以
jar
和aar
依赖方式参与构建的输入文件,包含本地依赖和远程依赖
- getOutPutProvider:获取 TransformOutputProvider 对象,它是对输出文件的描述,它有两个功能
- deleteAll:当 transform 以非增量构建模式时,需要删除上一次构建产生的所有中间文件,可以使用该方法
- getContentLocation:获得指定范围+类型的输出目标路径
2. transform 增量模式
任何构建系统都会尽量避免重复执行相同工作,transform 也提供了这样的备选项
-
增量标记位
- Transform#isIncremental():返回 true 才会触发增量模式
- TransformInvocation#isIncremental():表示 TransformTask 是否增量执行
-
Task 增量模式与 Transform 增量模式区别
前者会跳过整个 Task 的动作列表,后者还是会依次执行 TransformTask,但输入内容胡增加变更内容信息
-
增量模式的输入
此模式下的输入都是带状态的,需要根据这些状态做不同处理,无需每次都执行所有流程;例如新增的输入需要处理,未修改的输入就无需处理,Transform 定义了4个输入文件状态
// com.android.build.api.transform\Status.java @Deprecated public enum Status { // 未修改,无需处理,也无需复制操作 NOTCHANGED, // 新增,正常处理并复制给下一个任务 ADDED, // 已修改,正常处理并复制给下一个任务 CHANGED, // 已删除,需同步移除 OutputProvider 指定的目标文件 REMOVED; }
3. 注册 Transform
Gradle:com.android.tools.build:gradle-7.0.2.jar
下的 BaseExtension 中维护了 Transform 列表,自定义 Transform 需要注册才能生效,并且还支持设置 TransformTask 的依赖
// com.android.build.gradle\BaseExtension.kt
bstract class BaseExtension protected constructor(
protected val dslServices: DslServices,
protected val globalScope: GlobalScope,
...
):AndroidConfig, Lockable {
private val _transforms: MutableList<Transform> = mutableListOf()
/** Secondary dependencies for the custom transform. */
private val _transformDependencies: MutableList<List<Any>> = mutableListOf()
...
fun registerTransform(transform: Transform, vararg dependencies: Any) {
_transforms.add(transform)
_transformDependencies.add(listOf(dependencies))
}
}
注册 Transform:
// 获取 Android 扩展
val androidExt = project.extensions.getByType(BaseExtension::class.java)
// 注册 Transform,支持额外增加依赖
androidExt.registerTransform(MyTransform())