Project
是由Task
组成,每个 Task 负责完成一个基本工作,例如 javac 编译 task,transform 也是依靠 Task(TransformTask ) 执行的,在配置阶段, Gradle 会为注册的 Transform 创建对应的 Task(TransformTask )
而 Task 的依赖关系是通过 TransformTask 的输入输出关系隐式确定的,TransformManager 通过 TransformStream 链接各个 TransformTask 的输入输出,进而控制 Transform 的依赖关系顺序
我们先从 Plugin 的注册 transform 开始:
// MyPlugin.groovy
void apply(Project project){
def baseExt = project.extensions.getByType(BaseExtension.class)
baseExt.registerTransform(new MyTransform2(project))
}
接着进入 BaseExtension 看看,这个类维护了所有 Transform
// com.android.build.gradle\BaseExtension.kt
fun registerTransform(transform: Transform, vararg dependencies: Any) {
_transforms.add(transform)
_transformDependencies.add(listOf(dependencies))
}
override val transforms: List<Transform>
get() = ImmutableList.copyOf(_transforms)
查看 transforms
变量的调用,找到LibraryTaskManager.java
,我们看看该类
// com.android.build.gradle.internal\LibraryTaskManager.java
public class LibraryTaskManager extends TaskManager<LibraryVariantBuilderImpl, LibraryVariantImpl> {
@Override
protected void doCreateTasksForVariant(..){
...
// ----- External Transforms -----
// apply all the external transforms.
List<Transform> customTransforms = extension.getTransforms();
}
}
发现在 doCreateTasksForVariant 方法中有调用,该类的父类是 TaskManager,感兴趣的可以去翻翻它们看看,我这里将方法调用链进行列举
// com.android.build.gradle.internal
TaskManager.java
-> doCreateTasksForVariant() // 【注1】
-> createTasksForVariant()
-> createTasks()
// com.android.build.gradle.internal.plugins
BasePlugin.java
-> createAndroidTasks()
-> createTasks() // 【注2】project.afterEvaluate()中调用 createAndroidTasks()
-> basePluginApply()
-> apply()// 【注3】
// com.android.build.gradle.internal.plugins
LibraryPlugin.java // 【注4】
【注1】执行 doCreateTasksForVariant 抽象方法,具体到实现类为LibraryTaskManager
,Library 模块仅只支持使用 Scope.PROJECT 作用域。自定义插件不涉及ApplicationTaskManager
// com.android.build.gradle.internal\LibraryTaskManager.java
public class LibraryTaskManager extends TaskManager<LibraryVariantBuilderImpl, LibraryVariantImpl> {
...
@Override
protected void doCreateTasksForVariant(..){
...
// ----- External Transforms -----
// apply all the external transforms.
List<Transform> customTransforms = extension.getTransforms();
...
for (int i = 0, count = customTransforms.size(); i < count; i++) {
Transform transform = customTransforms.get(i);
// Library 模块仅只支持使用 Scope.PROJECT 作用域
Sets.SetView<? super Scope> difference =
Sets.difference(transform.getScopes(), TransformManager.PROJECT_ONLY);
...
// 将 transfrom 添加到 TransformManager 中
transformManager.addTransform(
taskFactory,
libraryVariant,
transform,...)
}
}
}
我们进入 TransformManager 看看添加 transform 的方法,看到 TransformTask 的 TaskName 有相应的规范transform[InputTypes]with[name]For[componentName]
// com.android.build.gradle.internal.pipeline
public class TransformManager extends FilterableStreamCollection {
...
public <T extends Transform> Optional<TaskProvider<TransformTask>> addTransform(..){
...
// TaskName = transform[InputTypes]with[name]For[componentName]
String taskName = creationConfig.computeTaskName(getTaskNamePrefix(transform), "");
...
}
...
// TaskName 前缀 :transform[InputTypes]with[name]For
static String getTaskNamePrefix(@NonNull Transform transform) {
StringBuilder sb = new StringBuilder(100);
sb.append("transform");
sb.append(
transform
.getInputTypes()
.stream()
.map(
inputType ->
CaseFormat.UPPER_UNDERSCORE.to(
CaseFormat.UPPER_CAMEL, inputType.name()))
.sorted() // Keep the order stable.
.collect(Collectors.joining("And")));
sb.append("With");
StringHelper.appendCapitalized(sb, transform.getName());
sb.append("For");
return sb.toString();
}
}
public abstract class TransformTask extends StreamBasedTask {
//...
@Input
@NonNull
public Set<QualifiedContent.ContentType> getInputTypes() {
return transform.getInputTypes();
}
...
@OutputDirectory
@Optional
@NonNull
public abstract DirectoryProperty getOutputDirectory()
}
通过 @Input 和 @OutputDirectory 将 Transform 与 TransformTask 进行关联
再看看 transform 方法,每个 TransformTask 内部都包含一个 CreationAction,执行 TransformTask 就是执行该 Action,用户通过 @TaskAction 添加默认 Action
@TaskAction
void transform(final IncrementalTaskInputs incrementalTaskInputs)
throws IOException, TransformException, InterruptedException {
...
u analyticsService = getAnalyticsService().get();
...
analyticsService.recordBlock(
ExecutionType.TASK_TRANSFORM,
executionInfo,
getProjectPath().get(),
getVariantName(),
new Recorder.VoidBlock() {
@Override
public void call() {
...
transform.transform(
new TransformInvocationBuilder(context)
.addInputs(consumedInputs.getValue())
.addReferencedInputs(referencedInputs.getValue())
.addSecondaryInputs(changedSecondaryInputs.getValue())
.addOutputProvider(
outputStream != null
? outputStream.asOutput()
: null)
.setIncrementalMode(isIncremental.getValue())
.build());
}
}
}