0%

构建编译Task替换

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public abstract class ReplaceTask<T extends Task, S extends Task> {
public ReplaceTask() {
}

public abstract Class<S> getReplaceTaskClass();

public abstract Class<T> getCustomTaskClass();


public void replace(Project project) {
List<Task> replaceTasks = new ArrayList<>();
//1.
for (Task task : project.getTasks()) {
if (task.getClass().getName().startsWith(getReplaceTaskClass().getName())) {
replaceTasks.add(task);
}
}
//2.
for (Task replaceTask : replaceTasks) {
project.getTasks().remove(replaceTask);
}

for (Task replaceTask : replaceTasks) {
//3.
Task task = project.getTasks().create(replaceTask.getName(), getCustomTaskClass());
//4.
task.dependsOn(replaceTask.getDependsOn());
}

}
}

解析

  1. for循环遍历 TaskContainer,收集需要替换的Task
  2. 从TaskContainer中先移除对应Class类型的Task
  3. for循环遍历收集到的需要替换的Task,然后用被替换Task的name创建新的task
  4. 把被替换task的依赖设置到新的task中

    疑问

  • 为什么循环遍历 TaskContainer,收集需要替换的Task?

因为taskcontainer配置阶段会根据构建变体生成同一类型的多个task
例如:
class : ProcessAndroidResources.class
task : processDebugResources和processReleaseReousrces

  • 为什么从TaskContainer中先移除对应Class类型的Task?

因为创建的时候,task会被添加到TaskContainer中,如果任务重复,会报异常
例如:
Cannot add task ‘processReleaseResources’ as a task with that name already exists.

  • 为什么使用startsWith? (task.getClass().getName().startsWith(getReplaceTaskClass().getName()))

因为task.getClass().getName()获取到的Class会有后缀
例如:
ProcessAndroidResources_Decorated

  • 还有没有简洁的方式替换?

TaskContainer 提供了replace方法

1
2
3
4
5
6
7
8
9
10
11
12
13
public void replace2(Project project) {
List<Task> replaceTasks = new ArrayList<>();
for (Task task : project.getTasks()) {
if (task.getClass().getName().startsWith(getReplaceTaskClass().getName())) {
replaceTasks.add(task);
}
}

for (Task replaceTask : replaceTasks) {
Task task = project.getTasks().replace(replaceTask.getName(), getCustomTaskClass());
task.dependsOn(replaceTask.getDependsOn());
}
}

运行

GenerateBuildConfigReplace

1
2
3
4
5
6
7
8
9
10
11
public class GenerateBuildConfigReplace extends ReplaceTask<GenerateBuildConfigExt, GenerateBuildConfig>{
@Override
public Class<GenerateBuildConfig> getReplaceTaskClass() {
return GenerateBuildConfig.class;
}

@Override
public Class<GenerateBuildConfigExt> getCustomTaskClass() {
return GenerateBuildConfigExt.class;
}
}

CustomTask

1
2
3
4
5
6
7
8
9
10
11
public class GenerateBuildConfigExt extends BaseTask {

public void action(){
setVariantName("debug"); //设置一下,因为编译过程需要获取构建变体
}

@TaskAction
public void process(){
System.out.println("我被替换了");
}
}

替换结果
image.png

编译运行结果
image.png

编译过程中,替换task很简单,但是实现替换的task是很复杂的,有的task我们可以继承,但是继承之后的task的输入输出需要我们重新实现;如果task中有些是私有变量,我们无法赋值,我们就得重新定制Task。

本例中只是列举了一个很简单的例子,替换了GenerateBuildConfig任务,编译过程并不会生成BuildConfig,因为demo中没有引用BuildConfig,所以可以正常编译通过。