代码
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<>(); for (Task task : project.getTasks()) { if (task.getClass().getName().startsWith(getReplaceTaskClass().getName())) { replaceTasks.add(task); } } for (Task replaceTask : replaceTasks) { project.getTasks().remove(replaceTask); } for (Task replaceTask : replaceTasks) { Task task = project.getTasks().create(replaceTask.getName(), getCustomTaskClass()); task.dependsOn(replaceTask.getDependsOn()); }
} }
|
解析
- for循环遍历 TaskContainer,收集需要替换的Task
- 从TaskContainer中先移除对应Class类型的Task
- for循环遍历收集到的需要替换的Task,然后用被替换Task的name创建新的task
- 把被替换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("我被替换了"); } }
|
替换结果
编译运行结果
编译过程中,替换task很简单,但是实现替换的task是很复杂的,有的task我们可以继承,但是继承之后的task的输入输出需要我们重新实现;如果task中有些是私有变量,我们无法赋值,我们就得重新定制Task。
本例中只是列举了一个很简单的例子,替换了GenerateBuildConfig任务,编译过程并不会生成BuildConfig,因为demo中没有引用BuildConfig,所以可以正常编译通过。