最近在學(xué)習(xí)自定義Gradle插件,怎么說(shuō)呢,過(guò)程相對(duì)曲折,結(jié)果相對(duì)滿意。在涉及到Gradle時(shí)也愿意去更多的了解一下,所以這篇文章是看Gradle源碼做的記錄整理,廢話不多說(shuō),直入主題。
在application模塊的build script中往往第一句就是
apply plugin: 'com.android.application'
在library模塊中的build script中第一行是:
apply plugin: 'com.android.library'
我們?cè)僖玫谌降囊恍┎寮蚴俏覀冏远x的插件時(shí),常常也是這一句:
apply plugin:'xxx'
com.android.application插件對(duì)應(yīng)的是com.android.build.gradle.AppPlugin類(以下簡(jiǎn)稱為AppPlugin類),com.android.library插件對(duì)應(yīng)的是com.android.build.gradle.LibraryPlugin類(以下簡(jiǎn)稱為L(zhǎng)ibraryPlugin類)。
看一下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類是一個(gè)抽象類,所以AppPlugin和LibraryPlugin的類結(jié)構(gòu)是相同的,參考圖1。從上面的代碼中可以看出,AppPlugin和LibraryPlugin也只是重寫了BasePlugin中定義的四個(gè)方法(LibraryPlugin還重寫了一個(gè)isLibrary方法),所以代碼都比較簡(jiǎn)單。
下面開始逐個(gè)方法去解析。既然build script中的第一行都是apply plugin 'xxx',那就從apply方法開始。AppPlugin和LibraryPlugin的apply方法中的邏輯都比較簡(jiǎn)單,大概遵從以下的邏輯。
@Override
void apply(Project project) {
super.apply(project)
...
}
super.apply自然就是執(zhí)行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實(shí)現(xiàn)了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 {...}
簡(jiǎn)單地說(shuō),Recorder是一個(gè)block執(zhí)行記錄,而且注釋中還給出了block的解釋:block就是一個(gè)可能返回?cái)?shù)值,可能拋出異常的代碼塊。
再看一下Recorder#Block類,這是個(gè)實(shí)現(xiàn)了Callable的抽象類,直接可以理解為一個(gè)線程即可,線程中的邏輯才是我們探究的重點(diǎn)。
在移除了一些次重要的代碼后,BasePlugin#apply的主要邏輯開始顯現(xiàn)出來(lái),如果再將一些代碼簡(jiǎn)化,apply方法邏輯就再直接不過(guò)了。
protected void apply(Project project) throws IOException {
configureProject();
createExtension();
createTasks();
}
即,apply做的工作如下:
- 配置project
- 配置extensions
- 創(chuàng)建tasks
configureProject做了什么
protected void configureProject() {
extraModelInfo = new ExtraModelInfo(project, isLibrary());
//檢測(cè)Gradle版本
checkGradleVersion();
//創(chuàng)建一個(gè)handler
sdkHandler = new SdkHandler(project, getLogger());
//創(chuàng)建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);
//應(yīng)用 JavaBasePlugin
project.getPlugins().apply(JavaBasePlugin.class);
//應(yīng)用 JacocoPlugin
jacocoPlugin = project.getPlugins().apply(JacocoPlugin.class);
//描述assemble task
project.getTasks().getByName("assemble").setDescription(
"Assembles all variants of all applications and secondary packages.");
//設(shè)置BuildListener監(jiān)聽(tīng)器
// 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);
}
}
});
//設(shè)置TaskExecutionGraphListener,監(jiān)聽(tīng)任務(wù)圖(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代碼中做了一些必要的注釋。且尚不管其中的元素發(fā)揮的作用。我們可以發(fā)現(xiàn)其中的邏輯還是很簡(jiǎn)單的:
- 檢測(cè)了Gradle版本;
- 初始化了三個(gè)變量sdkHandler、androidBuilder、dataBindingBuilder;
- 應(yīng)用了兩個(gè)插件JavaBasePlugin、JacocoPlugin;
- 添加了兩個(gè)對(duì)Gradle生命周期監(jiān)聽(tīng)的監(jiān)聽(tīng)器BuildListener、TaskExecutionGraphListener;
DONE!完了。
createExtension做了什么
private void createExtension() {
//創(chuàng)建buildTypeContainer
final NamedDomainObjectContainer<BuildType> buildTypeContainer = project.container(
BuildType.class,
new BuildTypeFactory(instantiator, project, project.getLogger()));
//創(chuàng)建productFlavorContainer
final NamedDomainObjectContainer<ProductFlavor> productFlavorContainer = project.container(
ProductFlavor.class,
new ProductFlavorFactory(instantiator, project, project.getLogger(), extraModelInfo));
//創(chuàng)建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());
//有疑問(wèn)
// 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.");
//創(chuàng)建依賴管理器
DependencyManager dependencyManager = new DependencyManager(project, extraModelInfo);
//創(chuàng)建與NDK有關(guān)系的ndkHandler
ndkHandler = new NdkHandler(
project.getRootDir(),
null, /* compileSkdVersion, this will be set in afterEvaluate */
"gcc",
"" /*toolchainVersion*/);
//創(chuàng)建任務(wù)管理器
taskManager = createTaskManager(
project,
androidBuilder,
dataBindingBuilder,
extension,
sdkHandler,
ndkHandler,
dependencyManager,
registry);
//創(chuàng)建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容器中添加元素時(shí)的回調(diào) */
// 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方法看著挺長(zhǎng),可是仔細(xì)再看,發(fā)現(xiàn)里面的元素不都是build script中經(jīng)常見(jiàn)到的代碼塊么:buildType、productFlavor、signingConfig。其他的諸如taskManager與task有關(guān),variantFactory、variantManager應(yīng)該與構(gòu)建變體有關(guān)。
其中涉及到一些類,做一下說(shuō)明,
- NamedDomainObjectContainer
從代碼中也能推測(cè)出這是一種容器。看一下源代碼中的注釋,可知NamedDomainObjectContainer是SortedSet的子類,所以,保持了Set容器的一些特點(diǎn)。
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",...),這個(gè)自然就是build script中的 android{...}塊。
android{
defaultConfig{
...
}
...
}
兩個(gè)管理器類
DependencyManager
解析依賴配置的管理器TaskManager
任務(wù)管理器,主要是在創(chuàng)建任務(wù)使用。VariantFactory
createVariantFactory方法返回類型,該方法是一個(gè)抽象方法,在AppPlugin和LibraryPlugin中分別有著具體的實(shí)現(xiàn)。signingConfigContainer,buildTypeContainer,productFlavorContainer容器中添加元素時(shí)回調(diào)??梢钥吹交卣{(diào)中都調(diào)用variantManager.addXxx,也正印證signingConfig、buildType、productFlavor都可以成為構(gòu)建變體的組成部分。
createTasks做了什么
private void createTasks() {
taskManager.createTasksBeforeEvaluate(new TaskContainerAdaptor(project.getTasks()));
project.afterEvaluate(new Action<Project>() {
@Override
public void execute(Project project) {
createAndroidTasks(false);
}
});
}
顧名思義,createTasks方法就是用來(lái)創(chuàng)建任務(wù)??梢钥吹皆摲椒ㄖ兄饕婕癰eforeEvaluate、afterEvaluate兩個(gè)階段的方法調(diào)用。AndroidTask 是依賴配置項(xiàng)的配置才能生成相應(yīng)任務(wù),所以是需要在 afterEvaluate 之后創(chuàng)建。所以,重點(diǎn)查看 afterEvaluate 階段的 createAndroidTasks方法。
VariantManager#createAndroidTasks
public void createAndroidTasks() {
...
//variantDataList 構(gòu)建變體數(shù)據(jù)集。variantDataList為空,則進(jìn)行填充
...
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做了代碼簡(jiǎn)化,只保留了主干。代碼注釋也很明了,就不再贅述。如果variantDataList為空,就以build script中的buildType, productFlavor等為原料去填充variantDataList。直接移步populateVariantDataList邏輯。
VariantManager#populateVariantDataList
/**
* Create all variants. 創(chuàng)建所有的構(gòu)建變體
*/
public void populateVariantDataList() {
//productFlavors類型為Map<String, ProductFlavorData<CoreProductFlavor>>
if (productFlavors.isEmpty()) {
createVariantDataForProductFlavors(Collections.<ProductFlavor>emptyList());
}
else {
...
}
}
查看productFlavors中有無(wú)元素,若沒(méi)有元素,則填充productFlavorsList。移步VariantManager#createVariantDataForProductFlavors
private void createVariantDataForProductFlavors(
@NonNull List<ProductFlavor> productFlavorList) {
BuildTypeData testBuildTypeData = null;
...
BaseVariantData variantForAndroidTest = null;
//獲取過(guò)濾變體
Action<com.android.build.gradle.api.VariantFilter> variantFilterAction =
extension.getVariantFilter();
//遍歷buildType
for (BuildTypeData buildTypeData : buildTypes.values()) {
boolean ignore = false;
//過(guò)濾變體
if (variantFilterAction != null) {
...
ignore = variantFilter.isIgnore();
}
//此時(shí)ignore == true,跳過(guò)if判斷
if (!ignore) {
/* 一個(gè)buildType + productFlavorList 創(chuàng)建variantData,添加到variantDataList */
BaseVariantData<?> variantData = createVariantData(
buildTypeData.getBuildType(),
productFlavorList);
variantDataList.add(variantData);
GradleVariantConfiguration variantConfig = variantData.getVariantConfiguration();
...
//存在Gradle測(cè)試代碼
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方法中,會(huì)遍歷buildType,每一種buildType再與productFlavorList中的每一種productFlavor組合成為構(gòu)建變體。這個(gè)過(guò)程在下面的createVariantData方法中實(shí)現(xiàn)。注意createVariantData返回BaseVariantData類型的對(duì)象,添加到variantDataList中。variantDataList是VariantManager的一個(gè)全局變量。
Gradle 會(huì)為配置的productFlavor與buildType的每個(gè)可能的組合創(chuàng)建構(gòu)建變體。不過(guò),某些特定的構(gòu)建變體在項(xiàng)目環(huán)境中可能并不必要,也可能沒(méi)有意義。所以,在模塊級(jí)build.gradle文件中創(chuàng)建一個(gè)變體過(guò)濾器,以移除某些構(gòu)建變體配置。所以,createVariantDataForProductFlavors方法中還對(duì)可能存在的過(guò)濾變體進(jìn)行處理。以下是AndroidDeveloper文檔中給出的一段示例代碼,過(guò)濾掉組合“minApi21”和“demo”產(chǎn)品風(fēng)格的所有構(gòu)建變體配置。
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
/**
* 給定一個(gè)buildType,一個(gè)集合ProductFlavor集合。
* 創(chuàng)建由該buildType和每一個(gè)ProductFlavor的構(gòu)建變體
* 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接口中方法,具體實(shí)現(xiàn)在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有相應(yīng)的具體實(shí)現(xiàn)。分別看一下具體實(shí)現(xiàn)。
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方法中最顯眼也是最熟悉的的兩個(gè)Set<String>類型的對(duì)象:densities、abis。針對(duì)不同的 ABI(應(yīng)用程序二進(jìn)制接口)或(density)屏幕密度,可以構(gòu)建多個(gè) APK。通常做法是在android塊中。
android{
splits {
// Configures multiple APKs based on screen density.
density {
...
}
abi{
...
}
}
}
這樣在創(chuàng)建variant過(guò)程中,會(huì)同時(shí)結(jié)合每一種配置的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就更簡(jiǎn)單了,直接返回一個(gè)新建的LibraryVariantData對(duì)象。
以上是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不為空,就獲取所有產(chǎn)品口味組合的列表flavorComboList ,然后遍歷flavorComboList ,繼續(xù)調(diào)用VariantManager#createVariantDataForProductFlavors,后面邏輯就一樣了。populateVariantDataList方法調(diào)用到此結(jié)束。接著看VariantManager#createAndroidTasks下面的邏輯,
public void createAndroidTasks() {
...
//variantDataList具體填充邏輯
populateVariantDataList();
...
//Create top level test tasks. 創(chuàng)建頂級(jí)測(cè)試任務(wù)
taskManager.createTopLevelTestTasks(tasks, ...)
...
createTasksForVariantData(tasks, variantData);
...
taskManager.createReportTasks(variantDataList);
}
taskManager#createTopLevelTestTasks
根據(jù)注釋知道,這個(gè)方法是創(chuàng)建頂級(jí)測(cè)試任務(wù),這個(gè)方法略去。直接看VariantManager#createTasksForVariantData
/**
* Create tasks for the specified variantData.
為具體的構(gòu)建變體創(chuàng)建相關(guān)的tasks
*/
public void createTasksForVariantData(
final TaskFactory tasks,
final BaseVariantData<? extends BaseVariantOutputData> variantData) {
// assemble task用于組合項(xiàng)目中的所有輸出。添加assemble task對(duì)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, 先忽略測(cè)試部分邏輯
if (variantType.isForTesting()) {
...
} else {
taskManager.createTasksForVariantData(tasks, variantData);
}
}
assemble task用于組合項(xiàng)目中的所有輸出。createTasksForVariantData方法中,首先添加assemble task對(duì)buildType assemble task依賴。之后調(diào)用
VariantManager#createAssembleTaskForVariantData。
/**
* Create assemble task for VariantData.
* 為VariantData創(chuàng)建assemble task
*
* 為buildTypeAssembleTask, productFlavorAssembleTask 添加依賴
*/
private void createAssembleTaskForVariantData(
TaskFactory tasks,
final BaseVariantData<?> variantData) {
//測(cè)試variantType
if (variantData.getType().isForTesting()) {
variantData.assembleVariantTask = taskManager.createAssembleTask(tasks, variantData);
}
//非測(cè)試variantType
else {
BuildTypeData buildTypeData =
buildTypes.get(variantData.getVariantConfiguration().getBuildType().getName());
//productFlavors塊沒(méi)有配置
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);
//設(shè)置builtType assembleTask 依賴 variantData assemble task
// setup the task dependencies
// build type
buildTypeData.getAssembleTask().dependsOn(variantData.assembleVariantTask);
//設(shè)置各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返回的集合中是否有遺漏,如有遺漏,需要?jiǎng)?chuàng)建相關(guān)task,
//并設(shè)置依賴
// 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邏輯也比較簡(jiǎn)單,為buildType、productFlavor的 assembleTask添加對(duì)variantData.assembleVariantTask的依賴。
繼續(xù)看createTasksForVariantData中的邏輯。
taskManager#createTasksForVariantData
//上個(gè)方法的名字叫createAssembleTask,其中內(nèi)容是在做跟assemble task有關(guān)的操作。
//這個(gè)方法叫createTasks,其中邏輯自然就是創(chuàng)建各種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);
//創(chuàng)建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大體邏輯已經(jīng)走完。BasePlugin#apply邏輯也已完成。
后記 (仍存有的疑問(wèn))
createExtension方法中創(chuàng)建兩個(gè)配置塊的default-mapping、default-metadata都未接觸過(guò),所以這里存在一些疑問(wèn)。有知道的同學(xué)希望能不吝賜教。
// 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.");
還有就是在源碼中存在這一部分,這里提到一個(gè)Jack compiler,也是第一次聽(tīng),專門去查了下,這里有一篇關(guān)于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/
本文只是簡(jiǎn)單的跟了一下流程,其中很多細(xì)節(jié)都忽略了,在以后的學(xué)習(xí)過(guò)程中逐漸加深理解吧,文章在作者對(duì)Gradle相關(guān)有新的認(rèn)知后會(huì)繼續(xù)做出更改,感謝。