最近在学习自定义Gradle插件,怎么说呢,过程相对曲折,结果相对满意。在涉及到Gradle时也愿意去更多的了解一下,所以这篇文章是看Gradle源码做的记录整理,废话不多说,直入主题。
在application模块的build script中往往第一句就是
apply plugin: 'com.android.application'
在library模块中的build script中第一行是:
apply plugin: 'com.android.library'
我们再引用第三方的一些插件或是我们自定义的插件时,常常也是这一句:
apply plugin:'xxx'
com.android.application插件对应的是com.android.build.gradle.AppPlugin类(以下简称为AppPlugin类),com.android.library插件对应的是com.android.build.gradle.LibraryPlugin类(以下简称为LibraryPlugin类)。
看一下AppPlugin类和LibraryPlugin类的定义。
/**
* Gradle plugin class for 'application' projects.
*/
class AppPlugin extends BasePlugin implements Plugin<Project> {
@Inject
public AppPlugin(Instantiator instantiator, ToolingModelBuilderRegistry registry) {
super(instantiator, registry)
}
@Override
protected Class<? extends BaseExtension> getExtensionClass() {
return AppExtension.class
}
@Override
protected TaskManager createTaskManager(
@NonNull Project project,
@NonNull AndroidBuilder androidBuilder,
@NonNull DataBindingBuilder dataBindingBuilder,
@NonNull AndroidConfig extension,
@NonNull SdkHandler sdkHandler,
@NonNull NdkHandler ndkHandler,
@NonNull DependencyManager dependencyManager,
@NonNull ToolingModelBuilderRegistry toolingRegistry) {
return new ApplicationTaskManager(
project,
androidBuilder,
dataBindingBuilder,
extension,
sdkHandler,
ndkHandler,
dependencyManager,
toolingRegistry)
}
@Override
void apply(Project project) {
super.apply(project)
}
@Override
protected VariantFactory createVariantFactory() {
return new ApplicationVariantFactory(instantiator, androidBuilder, extension)
}
}
/**
* Gradle plugin class for 'library' projects.
*/
public class LibraryPlugin extends BasePlugin implements Plugin<Project> {
/**
* Default assemble task for the default-published artifact. this is needed for
* the prepare task on the consuming project.
*/
Task assembleDefault
@Inject
public LibraryPlugin(Instantiator instantiator, ToolingModelBuilderRegistry registry) {
super(instantiator, registry)
}
@Override
public Class<? extends BaseExtension> getExtensionClass() {
return LibraryExtension.class
}
@Override
protected VariantFactory createVariantFactory() {
return new LibraryVariantFactory(
instantiator,
androidBuilder,
(LibraryExtension) extension);
}
@Override
protected boolean isLibrary() {
return true;
}
@Override
protected TaskManager createTaskManager(
@NonNull Project project,
@NonNull AndroidBuilder androidBuilder,
@NonNull DataBindingBuilder dataBindingBuilder,
@NonNull AndroidConfig extension,
@NonNull SdkHandler sdkHandler,
@NonNull NdkHandler ndkHandler,
@NonNull DependencyManager dependencyManager,
@NonNull ToolingModelBuilderRegistry toolingRegistry) {
return new LibraryTaskManager(
project,
androidBuilder,
dataBindingBuilder,
extension,
sdkHandler,
ndkHandler,
dependencyManager,
toolingRegistry)
}
@Override
void apply(Project project) {
super.apply(project)
assembleDefault = project.tasks.create("assembleDefault")
}
}
AppPlugin和LibraryPlugin都继承自BasePlugin类,BasePlugin类是一个抽象类,所以AppPlugin和LibraryPlugin的类结构是相同的,参考图1。从上面的代码中可以看出,AppPlugin和LibraryPlugin也只是重写了BasePlugin中定义的四个方法(LibraryPlugin还重写了一个isLibrary方法),所以代码都比较简单。
下面开始逐个方法去解析。既然build script中的第一行都是apply plugin 'xxx',那就从apply方法开始。AppPlugin和LibraryPlugin的apply方法中的逻辑都比较简单,大概遵从以下的逻辑。
@Override
void apply(Project project) {
super.apply(project)
...
}
super.apply自然就是执行BasePlugin#apply,移步BasePlugin#apply如下,
protected void apply(Project project) throws IOException {
this.project = project;
...
ThreadRecorder.get().record(...,
new Recorder.Block<Void>() {
@Override
public Void call() throws Exception {
configureProject();
return null;
}
}, ...);
ThreadRecorder.get().record(...,
new Recorder.Block<Void>() {
@Override
public Void call() throws Exception {
createExtension();
return null;
}
}, ...);
ThreadRecorder.get().record(...,
new Recorder.Block<Void>() {
@Override
public Void call() throws Exception {
createTasks();
return null;
}
}, ...);
}
ThreadRecorder实现了Recorder接口,看一下Recorder接口的描述,
/**
* A {@link ExecutionRecord} recorder for a block execution.
*
* A block is some code that produces a result and may throw exceptions.
*/
public interface Recorder {...}
简单地说,Recorder是一个block执行记录,而且注释中还给出了block的解释:block就是一个可能返回数值,可能抛出异常的代码块。
再看一下Recorder#Block类,这是个实现了Callable的抽象类,直接可以理解为一个线程即可,线程中的逻辑才是我们探究的重点。
在移除了一些次重要的代码后,BasePlugin#apply的主要逻辑开始显现出来,如果再将一些代码简化,apply方法逻辑就再直接不过了。
protected void apply(Project project) throws IOException {
configureProject();
createExtension();
createTasks();
}
即,apply做的工作如下:
- 配置project
- 配置extensions
- 创建tasks
configureProject做了什么
protected void configureProject() {
extraModelInfo = new ExtraModelInfo(project, isLibrary());
//检测Gradle版本
checkGradleVersion();
//创建一个handler
sdkHandler = new SdkHandler(project, getLogger());
//创建AndroidBuilder
androidBuilder = new AndroidBuilder(
project == project.getRootProject() ? project.getName() : project.getPath(),
creator,
new GradleProcessExecutor(project),
new GradleJavaProcessExecutor(project),
extraModelInfo,
getLogger(),
isVerbose());
dataBindingBuilder = new DataBindingBuilder();
dataBindingBuilder.setPrintMachineReadableOutput(
extraModelInfo.getErrorFormatMode() ==
ExtraModelInfo.ErrorFormatMode.MACHINE_PARSABLE);
//应用 JavaBasePlugin
project.getPlugins().apply(JavaBasePlugin.class);
//应用 JacocoPlugin
jacocoPlugin = project.getPlugins().apply(JacocoPlugin.class);
//描述assemble task
project.getTasks().getByName("assemble").setDescription(
"Assembles all variants of all applications and secondary packages.");
//设置BuildListener监听器
// call back on execution. This is called after the whole build is done (not
// after the current project is done).
// This is will be called for each (android) projects though, so this should support
// being called 2+ times.
project.getGradle().addBuildListener(new BuildListener() {
private final LibraryCache libraryCache = LibraryCache.getCache();
@Override
public void buildStarted(Gradle gradle) { }
@Override
public void settingsEvaluated(Settings settings) { }
@Override
public void projectsLoaded(Gradle gradle) { }
@Override
public void projectsEvaluated(Gradle gradle) { }
@Override
public void buildFinished(BuildResult buildResult) {
ExecutorSingleton.shutdown();
sdkHandler.unload();
ThreadRecorder.get().record(ExecutionType.BASE_PLUGIN_BUILD_FINISHED,
new Recorder.Block() {
@Override
public Void call() throws Exception {
PreDexCache.getCache().clear(
new File(project.getRootProject().getBuildDir(),
FD_INTERMEDIATES + "/dex-cache/cache.xml"),
getLogger());
JackConversionCache.getCache().clear(
new File(project.getRootProject().getBuildDir(),
FD_INTERMEDIATES + "/jack-cache/cache.xml"),
getLogger());
libraryCache.unload();
Main.clearInternTables();
return null;
}
}, new Recorder.Property("project", project.getName()));
try {
ProcessRecorderFactory.shutdown();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
//设置TaskExecutionGraphListener,监听任务图(task graph)配置完成
project.getGradle().getTaskGraph().addTaskExecutionGraphListener(
new TaskExecutionGraphListener() {
@Override
public void graphPopulated(TaskExecutionGraph taskGraph) {
for (Task task : taskGraph.getAllTasks()) {
if (task instanceof TransformTask) {
if (((TransformTask) task).getTransform() instanceof DexTransform) {
PreDexCache.getCache().load(
new File(project.getRootProject().getBuildDir(),
FD_INTERMEDIATES + "/dex-cache/cache.xml"));
break;
}
} else if (task instanceof JillTask) {
JackConversionCache.getCache().load(
new File(project.getRootProject().getBuildDir(),
FD_INTERMEDIATES + "/jack-cache/cache.xml"));
break;
}
}
}
});
}
我在configureProject代码中做了一些必要的注释。且尚不管其中的元素发挥的作用。我们可以发现其中的逻辑还是很简单的:
- 检测了Gradle版本;
- 初始化了三个变量sdkHandler、androidBuilder、dataBindingBuilder;
- 应用了两个插件JavaBasePlugin、JacocoPlugin;
- 添加了两个对Gradle生命周期监听的监听器BuildListener、TaskExecutionGraphListener;
DONE!完了。
createExtension做了什么
private void createExtension() {
//创建buildTypeContainer
final NamedDomainObjectContainer<BuildType> buildTypeContainer = project.container(
BuildType.class,
new BuildTypeFactory(instantiator, project, project.getLogger()));
//创建productFlavorContainer
final NamedDomainObjectContainer<ProductFlavor> productFlavorContainer = project.container(
ProductFlavor.class,
new ProductFlavorFactory(instantiator, project, project.getLogger(), extraModelInfo));
//创建signingConfigContainer
final NamedDomainObjectContainer<SigningConfig> signingConfigContainer = project.container(
SigningConfig.class,
new SigningConfigFactory(instantiator));
//build script中的android块
extension = project.getExtensions().create("android", getExtensionClass(),
project, instantiator, androidBuilder, sdkHandler,
buildTypeContainer, productFlavorContainer, signingConfigContainer,
extraModelInfo, isLibrary());
//有疑问
// create the default mapping configuration.
project.getConfigurations().create("default-mapping")
.setDescription("Configuration for default mapping artifacts.");
project.getConfigurations().create("default-metadata")
.setDescription("Metadata for the produced APKs.");
//创建依赖管理器
DependencyManager dependencyManager = new DependencyManager(project, extraModelInfo);
//创建与NDK有关系的ndkHandler
ndkHandler = new NdkHandler(
project.getRootDir(),
null, /* compileSkdVersion, this will be set in afterEvaluate */
"gcc",
"" /*toolchainVersion*/);
//创建任务管理器
taskManager = createTaskManager(
project,
androidBuilder,
dataBindingBuilder,
extension,
sdkHandler,
ndkHandler,
dependencyManager,
registry);
//创建variantFactory及variantManager
variantFactory = createVariantFactory();
variantManager = new VariantManager(
project,
androidBuilder,
extension,
variantFactory,
taskManager,
instantiator);
// Register a builder for the custom tooling model
ModelBuilder modelBuilder = new ModelBuilder(
androidBuilder,
variantManager,
taskManager,
extension,
extraModelInfo,
ndkHandler,
new NativeLibraryFactoryImpl(ndkHandler),
isLibrary(),
AndroidProject.GENERATION_ORIGINAL);
registry.register(modelBuilder);
/* signingConfigContainer, buildTypeContainer, productFlavorContainer容器中添加元素时的回调 */
// map the whenObjectAdded callbacks on the containers.
signingConfigContainer.whenObjectAdded(new Action<SigningConfig>() {
@Override
public void execute(SigningConfig signingConfig) {
variantManager.addSigningConfig(signingConfig);
}
});
buildTypeContainer.whenObjectAdded(new Action<BuildType>() {
@Override
public void execute(BuildType buildType) {
SigningConfig signingConfig = signingConfigContainer.findByName(BuilderConstants.DEBUG);
buildType.init(signingConfig);
variantManager.addBuildType(buildType);
}
});
productFlavorContainer.whenObjectAdded(new Action<ProductFlavor>() {
@Override
public void execute(ProductFlavor productFlavor) {
variantManager.addProductFlavor(productFlavor);
}
});
// map whenObjectRemoved on the containers to throw an exception.
signingConfigContainer.whenObjectRemoved(
new UnsupportedAction("Removing signingConfigs is not supported."));
buildTypeContainer.whenObjectRemoved(
new UnsupportedAction("Removing build types is not supported."));
productFlavorContainer.whenObjectRemoved(
new UnsupportedAction("Removing product flavors is not supported."));
// create default Objects, signingConfig first as its used by the BuildTypes.
variantFactory.createDefaultComponents(
buildTypeContainer, productFlavorContainer, signingConfigContainer);
}
createExtension方法看着挺长,可是仔细再看,发现里面的元素不都是build script中经常见到的代码块么:buildType、productFlavor、signingConfig。其他的诸如taskManager与task有关,variantFactory、variantManager应该与构建变体有关。
其中涉及到一些类,做一下说明,
- NamedDomainObjectContainer
从代码中也能推测出这是一种容器。看一下源代码中的注释,可知NamedDomainObjectContainer是SortedSet的子类,所以,保持了Set容器的一些特点。
Note that a container is an implementation of {@link java.util.SortedSet}, which means that the container is guaranteed to only contain elements with unique names within this container. Furthermore, items are ordered by their name.
- extension
extension = project.getExtensions().create("android",...),这个自然就是build script中的 android{...}块。
android{
defaultConfig{
...
}
...
}
两个管理器类
DependencyManager
解析依赖配置的管理器TaskManager
任务管理器,主要是在创建任务使用。VariantFactory
createVariantFactory方法返回类型,该方法是一个抽象方法,在AppPlugin和LibraryPlugin中分别有着具体的实现。signingConfigContainer,buildTypeContainer,productFlavorContainer容器中添加元素时回调。可以看到回调中都调用variantManager.addXxx,也正印证signingConfig、buildType、productFlavor都可以成为构建变体的组成部分。
createTasks做了什么
private void createTasks() {
taskManager.createTasksBeforeEvaluate(new TaskContainerAdaptor(project.getTasks()));
project.afterEvaluate(new Action<Project>() {
@Override
public void execute(Project project) {
createAndroidTasks(false);
}
});
}
顾名思义,createTasks方法就是用来创建任务。可以看到该方法中主要涉及beforeEvaluate、afterEvaluate两个阶段的方法调用。AndroidTask 是依赖配置项的配置才能生成相应任务,所以是需要在 afterEvaluate 之后创建。所以,重点查看 afterEvaluate 阶段的 createAndroidTasks方法。
VariantManager#createAndroidTasks
public void createAndroidTasks() {
...
//variantDataList 构建变体数据集。variantDataList为空,则进行填充
...
if (variantDataList.isEmpty()) {
//variantDataList具体填充逻辑
populateVariantDataList();
}
// Create top level test tasks.
taskManager.createTopLevelTestTasks(tasks, !productFlavors.isEmpty());
for (final BaseVariantData<? extends BaseVariantOutputData> variantData : variantDataList) {
...
createTasksForVariantData(tasks, variantData);
...
}
taskManager.createReportTasks(variantDataList);
}
createAndroidTasks做了代码简化,只保留了主干。代码注释也很明了,就不再赘述。如果variantDataList为空,就以build script中的buildType, productFlavor等为原料去填充variantDataList。直接移步populateVariantDataList逻辑。
VariantManager#populateVariantDataList
/**
* Create all variants. 创建所有的构建变体
*/
public void populateVariantDataList() {
//productFlavors类型为Map<String, ProductFlavorData<CoreProductFlavor>>
if (productFlavors.isEmpty()) {
createVariantDataForProductFlavors(Collections.<ProductFlavor>emptyList());
}
else {
...
}
}
查看productFlavors中有无元素,若没有元素,则填充productFlavorsList。移步VariantManager#createVariantDataForProductFlavors
private void createVariantDataForProductFlavors(
@NonNull List<ProductFlavor> productFlavorList) {
BuildTypeData testBuildTypeData = null;
...
BaseVariantData variantForAndroidTest = null;
//获取过滤变体
Action<com.android.build.gradle.api.VariantFilter> variantFilterAction =
extension.getVariantFilter();
//遍历buildType
for (BuildTypeData buildTypeData : buildTypes.values()) {
boolean ignore = false;
//过滤变体
if (variantFilterAction != null) {
...
ignore = variantFilter.isIgnore();
}
//此时ignore == true,跳过if判断
if (!ignore) {
/* 一个buildType + productFlavorList 创建variantData,添加到variantDataList */
BaseVariantData<?> variantData = createVariantData(
buildTypeData.getBuildType(),
productFlavorList);
variantDataList.add(variantData);
GradleVariantConfiguration variantConfig = variantData.getVariantConfiguration();
...
//存在Gradle测试代码
if (variantFactory.hasTestScope()) {
TestVariantData unitTestVariantData = createTestVariantData(
variantData,
UNIT_TEST);
variantDataList.add(unitTestVariantData);
...
}
}
}
if (variantForAndroidTest != null) {
TestVariantData androidTestVariantData = createTestVariantData(
variantForAndroidTest,
ANDROID_TEST);
variantDataList.add(androidTestVariantData);
}
}
在createVariantDataForProductFlavors方法中,会遍历buildType,每一种buildType再与productFlavorList中的每一种productFlavor组合成为构建变体。这个过程在下面的createVariantData方法中实现。注意createVariantData返回BaseVariantData类型的对象,添加到variantDataList中。variantDataList是VariantManager的一个全局变量。
Gradle 会为配置的productFlavor与buildType的每个可能的组合创建构建变体。不过,某些特定的构建变体在项目环境中可能并不必要,也可能没有意义。所以,在模块级build.gradle文件中创建一个变体过滤器,以移除某些构建变体配置。所以,createVariantDataForProductFlavors方法中还对可能存在的过滤变体进行处理。以下是AndroidDeveloper文档中给出的一段示例代码,过滤掉组合“minApi21”和“demo”产品风格的所有构建变体配置。
variantFilter { variant ->
def names = variant.flavors*.name
// To check for a certain build type, use variant.buildType.name == "<buildType>"
if (names.contains("minApi21") && names.contains("demo")) {
// Gradle ignores any variants that satisfy the conditions above.
setIgnore(true)
}
}
VariantManager#createVariantData
/**
* 给定一个buildType,一个集合ProductFlavor集合。
* 创建由该buildType和每一个ProductFlavor的构建变体
* Create a VariantData for a specific combination of BuildType and ProductFlavor list.
*/
public BaseVariantData<? extends BaseVariantOutputData> createVariantData(
@NonNull com.android.builder.model.BuildType buildType,
@NonNull List<? extends ProductFlavor> productFlavorList) {
BuildTypeData buildTypeData = buildTypes.get(buildType.getName());
GradleVariantConfiguration variantConfig = new GradleVariantConfiguration(
defaultConfigData.getProductFlavor(),
defaultConfigData.getSourceSet(),
buildTypeData.getBuildType(),
buildTypeData.getSourceSet(),
variantFactory.getVariantConfigurationType(),
signingOverride);
...
// sourceSetContainer in case we are creating variant specific sourceSets.
NamedDomainObjectContainer<AndroidSourceSet> sourceSetsContainer = extension
.getSourceSets();
// We must first add the flavors to the variant config, in order to get the proper
// variant-specific and multi-flavor name as we add/create the variant providers later.
for (ProductFlavor productFlavor : productFlavorList) {
ProductFlavorData<CoreProductFlavor> data = productFlavors.get(
productFlavor.getName());
String dimensionName = productFlavor.getDimension();
if (dimensionName == null) {
dimensionName = "";
}
//
variantConfig.addProductFlavor(
data.getProductFlavor(),
data.getSourceSet(),
dimensionName);
}
createCompoundSourceSets(productFlavorList, variantConfig, sourceSetsContainer);
...
// Done. Create the variant and get its internal storage object.
/* core
createVariantData为VariantFactory接口中方法,具体实现在ApplicationVariantFactory,
LibraryVariantFactory
*/
BaseVariantData<?> variantData =
variantFactory.createVariantData(variantConfig, taskManager);
final VariantDependencies variantDep = VariantDependencies.compute(
project, variantConfig.getFullName(),
isVariantPublished(),
variantData.getType(),
null,
variantProviders.toArray(new ConfigurationProvider[variantProviders.size()]));
variantData.setVariantDependency(variantDep);
...
return variantData;
}
variantFactory.createVariantData是接口方法,在ApplicationVariantFactory、LibraryVariantFactory有相应的具体实现。分别看一下具体实现。
ApplicationVariantFactory#createVariantData
@Override
@NonNull
public BaseVariantData createVariantData(
@NonNull GradleVariantConfiguration variantConfiguration,
@NonNull TaskManager taskManager) {
ApplicationVariantData variant =
new ApplicationVariantData(extension, variantConfiguration, taskManager,
androidBuilder.getErrorReporter());
variant.calculateFilters(extension.getSplits());
Set<String> densities = variant.getFilters(OutputFile.FilterType.DENSITY);
Set<String> abis = variant.getFilters(OutputFile.FilterType.ABI);
if (!densities.isEmpty()) {
variant.setCompatibleScreens(extension.getSplits().getDensity()
.getCompatibleScreens());
}
// create its outputs
if (variant.getSplitHandlingPolicy() ==
BaseVariantData.SplitHandlingPolicy.PRE_21_POLICY) {
// Always dd an entry with no filter for universal and add it FIRST,
// since code assume that the first variant output will be the universal one.
List<String> orderedDensities = new ArrayList<String>();
orderedDensities.add(NO_FILTER);
orderedDensities.addAll(densities);
List<String> orderedAbis = new ArrayList<String>();
// if the abi list is empty or we must generate a universal apk, add a NO_FILTER
if (abis.isEmpty() || (extension.getSplits().getAbi().isEnable() &&
extension.getSplits().getAbi().isUniversalApk())) {
orderedAbis.add(NO_FILTER);
}
orderedAbis.addAll(abis);
// create its outputs
for (String density : orderedDensities) {
for (String abi : orderedAbis) {
ImmutableList.Builder<FilterData> builder = ImmutableList.builder();
if (density != null) {
builder.add(FilterDataImpl.build(OutputFile.DENSITY, density));
}
if (abi != null) {
builder.add(FilterDataImpl.build(OutputFile.ABI, abi));
}
variant.createOutput(
OutputFile.OutputType.FULL_SPLIT,
builder.build());
}
}
} else {
variant.createOutput(OutputFile.OutputType.MAIN,
Collections.<FilterData>emptyList());
}
return variant;
}
ApplicationVariantFactory#createVariantData方法中最显眼也是最熟悉的的两个Set<String>类型的对象:densities、abis。针对不同的 ABI(应用程序二进制接口)或(density)屏幕密度,可以构建多个 APK。通常做法是在android块中。
android{
splits {
// Configures multiple APKs based on screen density.
density {
...
}
abi{
...
}
}
}
这样在创建variant过程中,会同时结合每一种配置的density、abi,这就是ApplicationVariantFactory#createVariantData方法的主要功能。
LibraryVariantFactory#createVariantData
@Override
@NonNull
public BaseVariantData createVariantData(
@NonNull GradleVariantConfiguration variantConfiguration,
@NonNull TaskManager taskManager) {
return new LibraryVariantData(extension, taskManager, variantConfiguration,
androidBuilder.getErrorReporter());
}
LibraryVariantFactory#createVariantData就更简单了,直接返回一个新建的LibraryVariantData对象。
以上是VariantManager#populateVariantDataList中if块,接着看else块中的逻辑
public void populateVariantDataList() {
//productFlavors类型为Map<String, ProductFlavorData<CoreProductFlavor>>
if (productFlavors.isEmpty()) {
...
}
else {
List<String> flavorDimensionList = extension.getFlavorDimensionList();
// Create iterable to get GradleProductFlavor from ProductFlavorData.
Iterable<CoreProductFlavor> flavorDsl =
Iterables.transform(
productFlavors.values(),
new Function<ProductFlavorData<CoreProductFlavor>, CoreProductFlavor>() {
@Override
public CoreProductFlavor apply(
ProductFlavorData<CoreProductFlavor> data) {
return data.getProductFlavor();
}
});
// Get a list of all combinations of product flavors.
List<ProductFlavorCombo<CoreProductFlavor>> flavorComboList =
ProductFlavorCombo.createCombinations(
flavorDimensionList,
flavorDsl);
for (ProductFlavorCombo<CoreProductFlavor> flavorCombo : flavorComboList) {
//noinspection unchecked
createVariantDataForProductFlavors(
(List<ProductFlavor>) (List) flavorCombo.getFlavorList());
}
}
}
如果productFlavors不为空,就获取所有产品口味组合的列表flavorComboList ,然后遍历flavorComboList ,继续调用VariantManager#createVariantDataForProductFlavors,后面逻辑就一样了。populateVariantDataList方法调用到此结束。接着看VariantManager#createAndroidTasks下面的逻辑,
public void createAndroidTasks() {
...
//variantDataList具体填充逻辑
populateVariantDataList();
...
//Create top level test tasks. 创建顶级测试任务
taskManager.createTopLevelTestTasks(tasks, ...)
...
createTasksForVariantData(tasks, variantData);
...
taskManager.createReportTasks(variantDataList);
}
taskManager#createTopLevelTestTasks
根据注释知道,这个方法是创建顶级测试任务,这个方法略去。直接看VariantManager#createTasksForVariantData
/**
* Create tasks for the specified variantData.
为具体的构建变体创建相关的tasks
*/
public void createTasksForVariantData(
final TaskFactory tasks,
final BaseVariantData<? extends BaseVariantOutputData> variantData) {
// assemble task用于组合项目中的所有输出。添加assemble task对build type task依赖
// Add dependency of assemble task on assemble build type task.
tasks.named("assemble", new Action<Task>() {
@Override
public void execute(Task task) {
BuildTypeData buildTypeData = buildTypes.get(
variantData.getVariantConfiguration().getBuildType().getName());
task.dependsOn(buildTypeData.getAssembleTask());
}
});
VariantType variantType = variantData.getType();
createAssembleTaskForVariantData(tasks, variantData);
//for test, 先忽略测试部分逻辑
if (variantType.isForTesting()) {
...
} else {
taskManager.createTasksForVariantData(tasks, variantData);
}
}
assemble task用于组合项目中的所有输出。createTasksForVariantData方法中,首先添加assemble task对buildType assemble task依赖。之后调用
VariantManager#createAssembleTaskForVariantData。
/**
* Create assemble task for VariantData.
* 为VariantData创建assemble task
*
* 为buildTypeAssembleTask, productFlavorAssembleTask 添加依赖
*/
private void createAssembleTaskForVariantData(
TaskFactory tasks,
final BaseVariantData<?> variantData) {
//测试variantType
if (variantData.getType().isForTesting()) {
variantData.assembleVariantTask = taskManager.createAssembleTask(tasks, variantData);
}
//非测试variantType
else {
BuildTypeData buildTypeData =
buildTypes.get(variantData.getVariantConfiguration().getBuildType().getName());
//productFlavors块没有配置
if (productFlavors.isEmpty()) {
// Reuse assemble task for build type if there is no product flavor.
variantData.assembleVariantTask = buildTypeData.getAssembleTask();
} else {
variantData.assembleVariantTask = taskManager.createAssembleTask(tasks, variantData);
//设置builtType assembleTask 依赖 variantData assemble task
// setup the task dependencies
// build type
buildTypeData.getAssembleTask().dependsOn(variantData.assembleVariantTask);
//设置各productFlavor assemble task 依赖 variantData assemble task
// each flavor
GradleVariantConfiguration variantConfig = variantData.getVariantConfiguration();
for (CoreProductFlavor flavor : variantConfig.getProductFlavors()) {
productFlavors.get(flavor.getName()).getAssembleTask()
.dependsOn(variantData.assembleVariantTask);
}
//variantConfig.getProductFlavors返回的集合中是否有遗漏,如有遗漏,需要创建相关task,
//并设置依赖
// assembleTask for this flavor(dimension), created on demand if needed.
if (variantConfig.getProductFlavors().size() > 1) {
final String name = StringHelper.capitalize(variantConfig.getFlavorName());
final String variantAssembleTaskName = "assemble" + name;
if (!tasks.containsKey(variantAssembleTaskName)) {
tasks.create(variantAssembleTaskName, new Action<Task>() {
@Override
public void execute(Task task) {
task.setDescription(
"Assembles all builds for flavor combination: " + name);
task.setGroup("Build");
task.dependsOn(variantData.assembleVariantTask);
}
});
}
tasks.named("assemble", new Action<Task>() {
@Override
public void execute(Task task) {
task.dependsOn(variantAssembleTaskName);
}
});
}
}
}
}
createAssembleTaskForVariantData逻辑也比较简单,为buildType、productFlavor的 assembleTask添加对variantData.assembleVariantTask的依赖。
继续看createTasksForVariantData中的逻辑。
taskManager#createTasksForVariantData
//上个方法的名字叫createAssembleTask,其中内容是在做跟assemble task有关的操作。
//这个方法叫createTasks,其中逻辑自然就是创建各种task了,从方法名就可以知道。
@Override
public void createTasksForVariantData(
@NonNull final TaskFactory tasks,
@NonNull final BaseVariantData<? extends BaseVariantOutputData> variantData) {
assert variantData instanceof ApplicationVariantData;
final VariantScope variantScope = variantData.getScope();
createAnchorTasks(tasks, variantScope);
//创建CheckManifestTask
createCheckManifestTask(tasks, variantScope);
...
// Create all current streams (dependencies mostly at this point)
createDependencyStreams(variantScope);
// Add a task to process the manifest(s)
...
createMergeAppManifestsTask(tasks, variantScope);
// Add a task to create the res values
...
createGenerateResValuesTask(tasks, variantScope);
// Add a task to compile renderscript files.
...
createRenderscriptTask(tasks, variantScope);
// Add a task to merge the resource folders
...
createMergeResourcesTask(tasks, variantScope);
// Add a task to merge the asset folders
createMergeAssetsTask(tasks, variantScope);
...
// Add a task to create the BuildConfig class
createBuildConfigTask(tasks, variantScope);
...
// Add a task to process the Android Resources and generate source files
createApkProcessResTask(tasks, variantScope);
createAidlTask(tasks, variantScope);
createShaderTask(tasks, variantScope);
// Add NDK tasks
createNdkTasks(variantScope);
variantScope.setNdkBuildable(getNdkBuildable(variantData));
// Add a task to merge the jni libs folders
createMergeJniLibFoldersTasks(tasks, variantScope);
// Add a compile task
AndroidTask<? extends JavaCompile> javacTask =
createJavacTask(tasks, variantScope);
...
if (variantData.getVariantConfiguration().getUseJack()) {
createJackTask(tasks, variantScope);
}
// Add data binding tasks if enabled
if (extension.getDataBinding().isEnabled()) {
createDataBindingTasks(tasks, variantScope);
}
if (variantData.getSplitHandlingPolicy().equals(
BaseVariantData.SplitHandlingPolicy.RELEASE_21_AND_AFTER_POLICY)) {
createSplitTasks(tasks, variantScope);
}
AndroidTask<InstantRunWrapperTask> fullBuildInfoGeneratorTask
= createInstantRunPackagingTasks(tasks, variantScope);
createPackagingTask(tasks, variantScope, true /*publishApk*/,
fullBuildInfoGeneratorTask);
// create the lint tasks.
createLintTasks(tasks, variantScope);
}
至此,VariantManager#createAndroidTasks大体逻辑已经走完。BasePlugin#apply逻辑也已完成。
后记 (仍存有的疑问)
createExtension方法中创建两个配置块的default-mapping、default-metadata都未接触过,所以这里存在一些疑问。有知道的同学希望能不吝赐教。
// create the default mapping configuration.
project.getConfigurations().create("default-mapping")
.setDescription("Configuration for default mapping artifacts.");
project.getConfigurations().create("default-metadata")
.setDescription("Metadata for the produced APKs.");
还有就是在源码中存在这一部分,这里提到一个Jack compiler,也是第一次听,专门去查了下,这里有一篇关于Jack编译器的博客,感兴趣的可以看看。
if (variantConfig.getType() == LIBRARY && variantConfig.getUseJack()) {
project.getLogger().warn(
"{}, {}: Jack compiler is not supported in library projects, falling back to javac.",
project.getPath(),
variantConfig.getFullName());
}
Jack compiler
http://taobaofed.org/blog/2016/05/05/new-compiler-for-android/
本文只是简单的跟了一下流程,其中很多细节都忽略了,在以后的学习过程中逐渐加深理解吧,文章在作者对Gradle相关有新的认知后会继续做出更改,感谢。