之前为了优化内部的Route, 去看了下TransformAPI
, 然后就顺便看了下AppPlugin
的源码.
本篇源码基于android gradle 3.0.1的版本.
总入口
我们直接从入口apply
开始看, 他调到了父类BasePlugin
的apply方法.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
33
34
35protected void apply(@NonNull Project project) {
// 一些基础path和插件版本的校验
// 以及一些流程记录的初始化
...
// 真正执行的是configureProject方法
// 项目配置
threadRecorder.record(
ExecutionType.BASE_PLUGIN_PROJECT_CONFIGURE,
project.getPath(),
null,
this::configureProject);
threadRecorder.record(
ExecutionType.BASE_PLUGIN_PROJECT_BASE_EXTENSION_CREATION,
project.getPath(),
null,
this::configureExtension);
threadRecorder.record(
ExecutionType.BASE_PLUGIN_PROJECT_TASKS_CREATION,
project.getPath(),
null,
this::createTasks);
}
public interface Recorder {
...
// record方法用来执行block, 然后将执行结果记录
void record(
@NonNull ExecutionType executionType,
@NonNull String projectPath,
@Nullable String variant,
@NonNull VoidBlock block);
}
apply
入口的代码非常简洁, 主要执行就三个方法, configureProject
, configureExtension
和createTasks
, 看方法名可以猜到, 他们的作用应该是配置Project, 配置插件的Extensions, 并且创建任务(task).
configureProject
1 | private void configureProject() { |
看代码我们可以梳理configureProject
流程如下
- 校验gradle版本
- 下载dependence
- 构建
androidBuilder
- 如果有设置
dataBinding
, 则会构建dataBindingBuilder
(这个不在本篇重点) - 分别引用
JavaBasePlugin
和JacocoPlugin
插件, 分别用于编译java代码成class和用于检查测试用例的覆盖率 - 注册taskGraph构建准备时的回调, 在准备完成时读取DexTransform的dex-cache缓存
- 注册编译完成时的回调, 进行dex缓存的清除工作
configureExtension
1 | private void configureExtension() { |
configureExtension
主要处理了extension
- 分别创建buildType, ProductFlavor, SigningConfig, BaseVariantOutput对应存储的集合对象
创建android Extension,
createExtension
是个抽象方法, 具体实现代码可以看AppPlugin
里, 在我们的工程配置gradle文件里, 就是我们熟悉的android闭包里的配置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
26protected BaseExtension createExtension(
@NonNull Project project,
@NonNull ProjectOptions projectOptions,
@NonNull Instantiator instantiator,
@NonNull AndroidBuilder androidBuilder,
@NonNull SdkHandler sdkHandler,
@NonNull NamedDomainObjectContainer<BuildType> buildTypeContainer,
@NonNull NamedDomainObjectContainer<ProductFlavor> productFlavorContainer,
@NonNull NamedDomainObjectContainer<SigningConfig> signingConfigContainer,
@NonNull NamedDomainObjectContainer<BaseVariantOutput> buildOutputs,
@NonNull ExtraModelInfo extraModelInfo) {
return project.getExtensions()
.create(
"android",
AppExtension.class,
project,
projectOptions,
instantiator,
androidBuilder,
sdkHandler,
buildTypeContainer,
productFlavorContainer,
signingConfigContainer,
buildOutputs,
extraModelInfo);
}分别创建
taskManager
和variantManager
, 看名字就可以知道他负责的分别是task和variant- 针对签名配置signingConfig, buildType, productFlavor 注册新增时候的监听, 对应添加到variantManager中做管理. 同时, 他们是不支持删除的.
- 创建默认的variant
createTasks
1 | private void createTasks() { |
在createTask
阶段, 首先会在配置收集之前(即在apply plugin)阶段会创建一些task, 这里TaskContainerAdaptor
可以理解为对task的又一层管理封装.
在配置收集获取所有task之后, 我们会调用到createAndroidTasks
在执行真正的创建tasks之前, 主要是对extension内一些配置进行校验, 譬如针对buildToolsVersion, compileSdkVersion是否指定, 是否另外引用了JavaPlugin等等, 这里的代码可以自行看源码了解1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23final void createAndroidTasks(boolean force) {
...
threadRecorder.record(
ExecutionType.VARIANT_MANAGER_CREATE_ANDROID_TASKS,
project.getPath(),
null,
// 根据variant创建tasks
() -> {
variantManager.createAndroidTasks();
ApiObjectFactory apiObjectFactory =
new ApiObjectFactory(
androidBuilder,
extension,
variantFactory,
instantiator,
project.getObjects());
for (VariantScope variantScope : variantManager.getVariantScopes()) {
BaseVariantData variantData = variantScope.getVariantData();
apiObjectFactory.create(variantData);
}
});
...
}
这里我们可以主要看下variantManager.createAndroidTasks()
方法内容, 这里根据variant创建对应的tasks
可以看到具体流程如下:
- 校验是否引用apt插件(这在3.0里使用annotationProcessor来声明注解处理器)
- 填充收集所以variant
- 根据variant创建对应的tasks
1 | public void createAndroidTasks() { |
总结
最后我们总结下, appPlugin
apply
的整体流程(当然, 因为他执行的是父类的apply
, 所以流程适用于libraryPlugin
)
- project的配置
- 检验gradle版本
- 下载dependence
- 构建
androidBuilder
- 引用
JavaBasePlugin
和JacocoPlugin
- 定义编译过程的回调, 负责处理dex-cache的加载和清除工作
- extension的配置
- 创建和配置extension
- 创建taskManager和variantManager
- 配置签名设置, buildType, productFlavor, 供后续task以及编译时使用
- 创建task(任务)
- 一些extension设置的检验
- 编译task的创建