compile 'com.android.tools.build:gradle:3.0.1'
複製代碼
經過這種方式,能夠直接依賴 plugin 的源碼,讀起來比較方便。
2. 官方對照源碼地址 android gradle plugin 源碼地址java
你們能夠直接 clone EasyGradle 項目,把 android-gradle-plugin-source/build.gradle 裏的 implementation 'com.android.tools.build:gradle:3.0.1' 註釋打開就能夠了。android
com.android.application 主要有下面幾個流程: git
在前面講解自定義插件的時候說到過,要定義一個 xxx.properties 文件,裏面聲明插件的入口類,而 xxx 就是 apply plugin 時候使用的 id,這裏要知道 android gradle plugin 的入口類,看 com.android.application.properties 文件就能夠,內容以下:github
implementation-class=com.android.build.gradle.AppPlugin
複製代碼
這裏定義了入口是 AppPlugin,AppPlugin 繼承自 BasePlugin。
AppPlugin 裏沒有作太多的操做,主要是重寫了 createTaskManager 和 createExtension,剩下的大部分工做仍是在 BasePlugin 裏作的。
插件準備工做中主要作的事情:緩存
// method: BasePlugin.apply()
checkPluginVersion();
複製代碼
// method: BasePlugin.apply()
// 方法中會遍歷全部子項目,判斷是否有重複的 id
this.checkModulesForErrors();
複製代碼
// method: BasePlugin.apply()
PluginInitializer.initialize(project, this.projectOptions);
// 建立 Profiler 文件
ProfilerInitializer.init(project, this.projectOptions);
// profiler 信息中寫入 plugin 版本
ProcessProfileWriter.getProject(project.getPath()).setAndroidPluginVersion(Version.ANDROID_GRADLE_PLUGIN_VERSION).setAndroidPlugin(this.getAnalyticsPluginType()).setPluginGeneration(PluginGeneration.FIRST);
複製代碼
配置項目這一階段主要作的事情:bash
// method: BasePlugin.configureProject()
this.checkGradleVersion();
複製代碼
this.project.getPlugins().apply(JavaBasePlugin.class);
this.project.getPlugins().apply(JacocoPlugin.class);
複製代碼
實如今 BasePlugin.configureExtension()
這一階段主要作了下面幾個事情:數據結構
this.extension = this.createExtension(...);
// AppPlugin 中實現了 createExtension,建立了 android {} dsl
protected BaseExtension createExtension(...) {
return (BaseExtension)project.getExtensions().create("android", AppExtension.class, new Object[]{project, projectOptions, instantiator, androidBuilder, sdkHandler, buildTypeContainer, productFlavorContainer, signingConfigContainer, buildOutputs, extraModelInfo});
}
複製代碼
// BasePlugin.java createExtension()
// map the whenObjectAdded callbacks on the containers.
signingConfigContainer.whenObjectAdded(variantManager::addSigningConfig);
buildTypeContainer.whenObjectAdded(
buildType -> {
SigningConfig signingConfig =
signingConfigContainer.findByName(BuilderConstants.DEBUG);
buildType.init(signingConfig);
// addBuildType,會檢查命名是否合法,而後建立 BuildTypeData
variantManager.addBuildType(buildType);
});
// addProductFlavor 會檢查命名是否合法,而後建立 ProductFlavorData
productFlavorContainer.whenObjectAdded(variantManager::addProductFlavor);
// VariantManager.java
// addSigningConfig 就是在 signingConfigs 裏新增一個配置
public void addSigningConfig(SigningConfig signingConfig) {
this.signingConfigs.put(signingConfig.getName(), signingConfig);
}
// VariantManager.java
public void addProductFlavor(CoreProductFlavor productFlavor) {
String name = productFlavor.getName();
// checkName 會檢查
checkName(name, "ProductFlavor");
if(this.buildTypes.containsKey(name)) {
throw new RuntimeException("ProductFlavor names cannot collide with BuildType names");
} else {
// 獲取源碼位置
DefaultAndroidSourceSet mainSourceSet = (DefaultAndroidSourceSet)this.extension.getSourceSets().maybeCreate(productFlavor.getName());
DefaultAndroidSourceSet androidTestSourceSet = null;
DefaultAndroidSourceSet unitTestSourceSet = null;
if(this.variantFactory.hasTestScope()) {
// 獲取單測源碼位置
androidTestSourceSet = (DefaultAndroidSourceSet)this.extension.getSourceSets().maybeCreate(computeSourceSetName(productFlavor.getName(), VariantType.ANDROID_TEST));
unitTestSourceSet = (DefaultAndroidSourceSet)this.extension.getSourceSets().maybeCreate(computeSourceSetName(productFlavor.getName(), VariantType.UNIT_TEST));
}
// 建立 productFlavorData 對象
ProductFlavorData<CoreProductFlavor> productFlavorData = new ProductFlavorData(productFlavor, mainSourceSet, androidTestSourceSet, unitTestSourceSet, this.project);
this.productFlavors.put(productFlavor.getName(), productFlavorData);
}
}
複製代碼
variantFactory.createDefaultComponents(
buildTypeContainer, productFlavorContainer, signingConfigContainer);
// ApplicationVariantFactory.java
public void createDefaultComponents(...) {
signingConfigs.create("debug");
buildTypes.create("debug");
buildTypes.create("release");
}
複製代碼
上述準備,配置階段完成之後,就開始建立構建須要的 Task 了,是在 BasePlugin.createTasks() 裏實現的,主要有兩步,建立不依賴 flavor 的 task 和建立構建 task。
先看不依賴 flavor 的 task,其實如今 TaskManager.createTasksBeforeEvaluate()。
這裏主要建立了幾個 task,包括 uninstallAll,deviceCheck,connectedCheck,preBuild,extractProguardFiles,sourceSets,assembleAndroidTest,compileLint,lint,lintChecks,cleanBuildCacheresolveConfigAttr,consumeConfigAttr。
這些 task 都是不須要依賴 flavor 數據的公共 task。app
在介紹下面的流程以前,先明確幾個概念,flavor,dimension,variant。
在 android gradle plugin 3.x 以後,每一個 flavor 必須對應一個 dimension,能夠理解爲 flavor 的分組,而後不一樣 dimension 裏的 flavor 組合成一個 variant。
舉個例子:ide
flavorDimensions "size", "color"
productFlavors {
big {
dimension "size"
}
small {
dimension "size"
}
blue {
dimension "color"
}
red {
dimension "color"
}
}
複製代碼
上面配置對應生成的 variant 就是 bigBlue,bigRed,smallBlue,smallRed,在這個基礎上,再加上 buildTypes,就是 bigBlueDebug,bigRedDebug,smallBlueDebug,smallRedDebug,bigBlueRelease,bigRedRelease,smallBlueRelease,smallRedRelease。函數
createAndroidTasks 的調用時機和上面不同,是在 project.afterEvaluate 裏調用的,還記得以前文章裏說道的 afterEvaluate 回調麼?這個時候全部模塊配置已經完成了。因此在這個階段能夠獲取到對應的 flavor 以及其餘配置了。
在 BasePlugin.createAndroidTasks 裏,是調用 VariantManager.createAndroidTasks 完成工做的。
建立 task 的時候,會先經過 populateVariantDataList 生成 flavor 相關的數據結構,而後調用 createTasksForVariantData 建立 flavor 對應的 task。
分別看下這兩個方法作的事情
1.populateVariantDataList
在方法裏,會先根據 flavor 和 dimension 建立對應的組合,存放在 flavorComboList 裏,以後調用 createVariantDataForProductFlavors 建立對應的 VariantData。
其中重要的幾個方法:
// 建立 flavor 和 dimension 的組合
List<ProductFlavorCombo<CoreProductFlavor>> flavorComboList =
ProductFlavorCombo.createCombinations(
flavorDimensionList,
flavorDsl);
// 爲每一個組合建立 VariantData
for (ProductFlavorCombo<CoreProductFlavor> flavorCombo : flavorComboList) {
//noinspection unchecked
createVariantDataForProductFlavors(
(List<ProductFlavor>) (List) flavorCombo.getFlavorList());
}
複製代碼
建立出來的 VariantData 都是 BaseVariantData 的子類,裏面保存了一些 Task,能夠看一下 BaseVariantData 裏的一些重要的結構,對 BaseVariantData 有個大概的瞭解。
public abstract class BaseVariantData implements TaskContainer {
private final GradleVariantConfiguration variantConfiguration;
private VariantDependencies variantDependency;
private final VariantScope scope;
public Task preBuildTask;
public Task sourceGenTask;
public Task resourceGenTask; // 資源處理
public Task assetGenTask;
public CheckManifest checkManifestTask; // 檢測manifest
public AndroidTask<PackageSplitRes> packageSplitResourcesTask; // 打包資源
public AndroidTask<PackageSplitAbi> packageSplitAbiTask;
public RenderscriptCompile renderscriptCompileTask;
public MergeResources mergeResourcesTask; // 合併資源
public ManifestProcessorTask processManifest; // 處理 manifest
public MergeSourceSetFolders mergeAssetsTask; // 合併 assets
public GenerateBuildConfig generateBuildConfigTask; // 生成 BuildConfig
public GenerateResValues generateResValuesTask;
public Sync processJavaResourcesTask;
public NdkCompile ndkCompileTask; // ndk 編譯
public JavaCompile javacTask;
public Task compileTask;
public Task javaCompilerTask; // java 文件編譯
// ...
}
複製代碼
VariantData 裏保存了不少 task,下一步就要建立這些 task。
2.createTasksForVariantData
建立完 variant 數據,就要給 每一個 variantData 建立對應的 task,對應的 task 有 assembleXXXTask,prebuildXXX,generateXXXSource,generateXXXResources,generateXXXAssets,processXXXManifest 等等,重點關注幾個方法:
VariantManager.createAssembleTaskForVariantData() // 建立 assembleXXXTask
TaskManager.createTasksForVariantScope() // 是一個抽象類,具體實如今 ApplicationTaskManager.createTasksForVariantScope()
TaskManager.createPostCompilationTasks() // 建立 .class to dex 的 task, 建立 transformTask,咱們建立的 transform 就是這個階段添加進來的,是在 addCompileTask 裏調用的
// createTasksForVariantScope 是一個抽象方法,具體實如今子類中,能夠看一下 ApplicationTaskManager.createTasksForVariantScope()
// createTasksForVariantScope 裏的實現,若是在業務中有須要查看相關 task 源碼時,能夠來這裏找
void createTasksForVariantScope() {
this.createCheckManifestTask(tasks, variantScope); // 檢測 manifest
this.handleMicroApp(tasks, variantScope);
this.createDependencyStreams(tasks, variantScope);
this.createApplicationIdWriterTask(tasks, variantScope); // application id
this.createMergeApkManifestsTask(tasks, variantScope); // 合併 manifest
this.createGenerateResValuesTask(tasks, variantScope);
this.createRenderscriptTask(tasks, variantScope);
this.createMergeResourcesTask(tasks, variantScope, true); // 合併資源文件
this.createMergeAssetsTask(tasks, variantScope, (BiConsumer)null); // 合併 assets
this.createBuildConfigTask(tasks, variantScope); // 生成 BuildConfig
this.createApkProcessResTask(tasks, variantScope); // 處理資源
this.createProcessJavaResTask(tasks, variantScope);
this.createAidlTask(tasks, variantScope); // 處理 aidl
this.createShaderTask(tasks, variantScope);
this.createNdkTasks(tasks, variantScope); // 處理 ndk
this.createExternalNativeBuildJsonGenerators(variantScope);
this.createExternalNativeBuildTasks(tasks, variantScope);
this.createMergeJniLibFoldersTasks(tasks, variantScope); // 合併 jni
this.createDataBindingTasksIfNecessary(tasks, variantScope); // 處理 databinding
this.addCompileTask(tasks, variantScope);
createStripNativeLibraryTask(tasks, variantScope);
this.createSplitTasks(tasks, variantScope);
this.createPackagingTask(tasks, variantScope, buildInfoWriterTask); // 打包 apk
this.createLintTasks(tasks, variantScope); // lint
}
// createPostCompilationTasks 實現:
// 處理 Android Transform
void createPostCompilationTasks() {
for (int i = 0, count = customTransforms.size(); i < count; i++) {
Transform transform = customTransforms.get(i);
// TransformManager.addTransform 其實是爲 transform 建立了一個 Task
transformManager
.addTransform(tasks, variantScope, transform)
.ifPresent(t -> {
if (!deps.isEmpty()) {
t.dependsOn(tasks, deps);
}
// if the task is a no-op then we make assemble task depend on it.
if (transform.getScopes().isEmpty()) {
variantScope.getAssembleTask().dependsOn(tasks, t);
}
});
}
}
複製代碼
android gradle plugin 的主要流程基本上就結束了,主要流程圖以下所示
這裏總結幾個要點: