1.根底筹备

在剖析源码之前,我想你应该对 Android 打包流程曾经有根底的理解,至多理解了下图的打包过程:

否则你有可能不理解下文中的专业术语。

2.AGP源码的打开方式

看 AGP 代码的时候,我始终纠结要不要下载 AGP 的源码,起初听共事大佬倡议,间接应用了我的项目依赖的代码进行剖析。

次要的起因有两点:

1. AGP 的源码太大了,有30g,并且版本曾经很旧了。

2. 应用我的项目依赖的 AGP 代码很简略。

只有在我的项目中退出

implementation "com.android.tools.build:gradle:4.1.1"  

即可查看。


3.代码剖析

顺便说一下,AGP 的版本是 4.1.1。

第一步 寻找AppPlugin

在 AS 中,如果创立了一个我的项目,默认在主模块上面增加:

apply plugin: 'com.android.application'  

自定义过 Plugin 的小伙伴都晓得,源码中肯定有一个 com.android.application.properties 文件与之绝对应,这便是咱们 Plugin 的入口了。

全局搜 com.android.application,关上 com.android.application.properties,内容是:

implementation-class=com.android.build.gradle.AppPlugin  

按「Command」按钮点击源码,发现 AppPlugin 外面又申明了一个 Plugin,最终跳到了:

implementation-class=com.android.build.gradle.internal.plugins.AppPlugin

包名与之前的不一样,这才是咱们的最终入口。

各位同学有没有这样的纳闷,我给加上 apply plugin: com.android.application,那这段代码什么时候调用呢?

不晓得大家有没有留神到,每次改变 build.gradle 文件的时候,AS 都会让咱们点击 「Sync Now」按钮,点击完了,就会触发 Gradle 中的配置过程,最终会运行 Plugin#apply 办法,大家能够自定义 Plugin 的时候验证一下。

第二步 AppPlugin

AppPlugin 的父类是 AbstractAppPlugin,AbstractAppPlugin 的父类是 BasePlugin,插件的开始就在 BasePlugin#apply 办法外面:

@Override  public final void apply(@NonNull Project project) {      CrashReporting.runAction(              () -> {                  basePluginApply(project);                  pluginSpecificApply(project);              });  }  

这里咱们只须要关注办法块外面的两个办法 basePluginApply 和 pluginSpecificApply。

进入重点办法 basePluginApply 办法,这个办法的后期做了很多的查看工作,包含门路、版本和 AGP 版本等等,之后又做了很多监听工作,看一下源码:

private void basePluginApply(@NonNull Project project) {      // ... 代码省略      // 依赖查看      DependencyResolutionChecks.registerDependencyCheck(project, projectOptions);      // ... 省略门路查看、模块查看等、构建参数监听器      // AGP版本查看      AgpVersionChecker.enforceTheSamePluginVersions(project);      // 构建流程Task执行的监听器      RecordingBuildListener buildListener = ProfilerInitializer.init(project, projectOptions);      ProfileAgent.INSTANCE.register(project.getName(), buildListener);      threadRecorder = ThreadRecorder.get();      //... 代码省略      // 重点      // 1. 配置我的项目      threadRecorder.record(              ExecutionType.BASE_PLUGIN_PROJECT_CONFIGURE,              project.getPath(),              null,              this::configureProject);      // 2. 配置扩大      threadRecorder.record(              ExecutionType.BASE_PLUGIN_PROJECT_BASE_EXTENSION_CREATION,              project.getPath(),              null,              this::configureExtension);      // 3. 创立Task      threadRecorder.record(              ExecutionType.BASE_PLUGIN_PROJECT_TASKS_CREATION,              project.getPath(),              null,              this::createTasks);  }  

其中的重点办法我曾经标注进去了,别离是配置我的项目、配置扩大和创立Task。

第三步 配置Project

须要留神的是,此配置并不是对应 Gradle 生命周期的配置,而是针对以后 Project 做一些配置工作。

private void configureProject() {      // ... 执行大量的Service      // 依赖版本相干      Provider<ConstraintHandler.CachedStringBuildService> cachedStringBuildServiceProvider =              new ConstraintHandler.CachedStringBuildService.RegistrationAction(project)                      .execute();      // maven缓存相干      Provider<MavenCoordinatesCacheBuildService> mavenCoordinatesCacheBuildService =              new MavenCoordinatesCacheBuildService.RegistrationAction(                      project, cachedStringBuildServiceProvider)                      .execute();      // 依赖库相干      new LibraryDependencyCacheBuildService.RegistrationAction(project).execute();      // aapt筹备工作      new Aapt2WorkersBuildService.RegistrationAction(project, projectOptions).execute();      new Aapt2DaemonBuildService.RegistrationAction(project).execute();      new SyncIssueReporterImpl.GlobalSyncIssueService.RegistrationAction(              project, SyncOptions.getModelQueryMode(projectOptions))              .execute();      // SDK相干      Provider<SdkComponentsBuildService> sdkComponentsBuildService =              new SdkComponentsBuildService.RegistrationAction(                      project,                      projectOptions,                      project.getProviders()                              .provider(() -> extension.getCompileSdkVersion()),                      project.getProviders()                              .provider(() -> extension.getBuildToolsRevision()),                      project.getProviders().provider(() -> extension.getNdkVersion()),                      project.getProviders().provider(() -> extension.getNdkPath()))                      .execute();      // Enforce minimum versions of certain plugins      GradlePluginUtils.enforceMinimumVersionsOfPlugins(project, issueReporter);      // Apply the Java plugin      project.getPlugins().apply(JavaBasePlugin.class);      dslServices =              new DslServicesImpl(                      projectServices,                      new DslVariableFactory(syncIssueReporter),                      sdkComponentsBuildService);      // 音讯打印服务注册      MessageReceiverImpl messageReceiver =              new MessageReceiverImpl(                      SyncOptions.getErrorFormatMode(projectOptions),                      projectServices.getLogger());      // ... 省略      createLintClasspathConfiguration(project);  }  

我对上述代码的了解是创立Task前的筹备工作,并且,下面代码中形容的 xxxAction 也很容易让人蛊惑,也并不是对应 Task 中的 Action。

第四步 确认扩大

确认扩大对应的办法就是 configureExtension。

通常在 app 模块下的 build.gradle 文件中,经常会有诸如此类的配置:

android {      compileSdk 32        defaultConfig {          applicationId "com.qidian.test"          minSdk 21          targetSdk 32          versionCode 1          versionName "1.0"            testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"      }        buildTypes {          release {              minifyEnabled false              proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'          }          debug {              minifyEnabled false          }      }      compileOptions {          sourceCompatibility JavaVersion.VERSION_1_8          targetCompatibility JavaVersion.VERSION_1_8      }      kotlinOptions {          jvmTarget = '1.8'      }  }

configureExtension 的目标就是为了将此类的脚本信息转化成代码能够辨认的信息:

private void configureExtension() {      // Gradle DSL的帮忙类      DslServices dslServices = globalScope.getDslServices();      final NamedDomainObjectContainer<BaseVariantOutput> buildOutputs =              project.container(BaseVariantOutput.class);      // ... 代码省略      // ... variant 的工厂类以及治理等等      variantFactory = createVariantFactory(projectServices, globalScope);      variantInputModel =              new LegacyVariantInputManager(                      dslServices,                      variantFactory.getVariantType(),                      new SourceSetManager(                              project,                              isPackagePublished(),                              dslServices,                              new DelayedActionsExecutor()));      // 创立扩大      extension =              createExtension(                      dslServices, globalScope, variantInputModel, buildOutputs, extraModelInfo);      globalScope.setExtension(extension);      variantManager =              new VariantManager<>(                      globalScope,                      project,                      projectServices.getProjectOptions(),                      extension,                      variantFactory,                      variantInputModel,                      projectServices,                      threadRecorder);      registerModels(              registry,              globalScope,              variantInputModel,              extension,              extraModelInfo);      // create default Objects, signingConfig first as its used by the BuildTypes.      variantFactory.createDefaultComponents(variantInputModel);      // ...   }  

简略看一下代码即可,发现大部分的代码都跟 variant 和扩大相干。

再关注一下生成的扩大,BasePlugin#createExtension 是个形象办法,最终交给了 AppPlugin#createExtension 办法:

protected AppExtension createExtension(          @NonNull DslServices dslServices,          @NonNull GlobalScope globalScope,          @NonNull                  DslContainerProvider<DefaultConfig, BuildType, ProductFlavor, SigningConfig>                  dslContainers,          @NonNull NamedDomainObjectContainer<BaseVariantOutput> buildOutputs,          @NonNull ExtraModelInfo extraModelInfo) {      return project.getExtensions()              .create(                      "android",                      getExtensionClass(),                      dslServices,                      globalScope,                      buildOutputs,                      dslContainers.getSourceSetManager(),                      extraModelInfo,                      new ApplicationExtensionImpl(dslServices, dslContainers));  }  

乍看仿佛还是不太熟悉,然而如果开发过插件,你肯定晓得 AppExtension,它能够获取到下面提及的 build.gradle 下的 android {} 中的任何信息。

第五步 创立Task

这应该是最重要的一步了,创立 Task 就在 BasePlugin#createTasks 办法:

private void createTasks() {      // 注册跟Variant不相干的工作      threadRecorder.record(              ExecutionType.TASK_MANAGER_CREATE_TASKS,              project.getPath(),              null,              () ->                      TaskManager.createTasksBeforeEvaluate(                              globalScope,                              variantFactory.getVariantType(),                              extension.getSourceSets()));      // 等到Gradle配置阶段实现后,注册跟Variant相干的工作      project.afterEvaluate(              CrashReporting.afterEvaluate(                      p -> {                          variantInputModel.getSourceSetManager().runBuildableArtifactsActions();                          threadRecorder.record(                                  ExecutionType.BASE_PLUGIN_CREATE_ANDROID_TASKS,                                  project.getPath(),                                  null,                                  this::createAndroidTasks);                      }));  }  

这个办法外面次要有两个办法:

1. TaskManager#createTasksBeforeEvaluate:静态方法示意在 Project 配置前,会创立一批 Task。

2. createAndroidTasks:注册了一个配置生命周期实现后的回调,等到 Project 配置实现后,Variant 曾经确定结束,又会创立一批 Task。

TaskManager#createTasksBeforeEvaluate 外面是一大段注册 Task 的代码,感兴趣能够本人查看源码。

第六步 配置实现后创立Task

等 Project 进入配置生命周期的回调,进入办法 createAndroidTasks:

final void createAndroidTasks() {      if (extension.getCompileSdkVersion() == null) {          // ... compileSdkVersion 相干      }      // ...      // get current plugins and look for the default Java plugin.      if (project.getPlugins().hasPlugin(JavaPlugin.class)) {          throw new BadPluginException(                  "The 'java' plugin has been applied, but it is not compatible with the Android plugins.");      }      // ...        // 设置一些配置      ProcessProfileWriter.getProject(project.getPath())              .setCompileSdk(extension.getCompileSdkVersion())              .setBuildToolsVersion(extension.getBuildToolsRevision().toString())              .setSplits(AnalyticsUtil.toProto(extension.getSplits()));        String kotlinPluginVersion = getKotlinPluginVersion();      if (kotlinPluginVersion != null) {          ProcessProfileWriter.getProject(project.getPath())                  .setKotlinPluginVersion(kotlinPluginVersion);      }      AnalyticsUtil.recordFirebasePerformancePluginVersion(project);      // 正文一 创立Variant      variantManager.createVariants();      List<ComponentInfo<VariantT, VariantPropertiesT>> variants =              variantManager.getMainComponents();      TaskManager<VariantT, VariantPropertiesT> taskManager =              createTaskManager(                      variants,                      variantManager.getTestComponents(),                      !variantInputModel.getProductFlavors().isEmpty(),                      globalScope,                      extension,                      threadRecorder);      // 正文二 创立Task      taskManager.createTasks();        // ...        // 正文三 创立 Task configure compose related tasks.      taskManager.createPostApiTasks();        // now publish all variant artifacts for non test variants since      // tests don't publish anything.      for (ComponentInfo<VariantT, VariantPropertiesT> component : variants) {          component.getProperties().publishBuildArtifacts();      }        // ...      variantManager.setHasCreatedTasks(true);      // notify our properties that configuration is over for us.      GradleProperty.Companion.endOfEvaluation();  }  

首先,从正文一中能够看出,所有的 Variant 在这一步曾经创立实现了。

接着,从正文二和正文三咱们能够看出,createAndroidTasks 先后两次应用 taskManager 创立 Task。

**第七步 TaskManager第一次创立多个Task

**

第一次创立 Task 应用的 TaskManager#createTasks 办法,点进这个办法:

public void createTasks() {      // lint相干的Task      taskFactory.register(new PrepareLintJarForPublish.CreationAction(globalScope));      // create a lifecycle task to build the lintChecks dependencies      taskFactory.register(              COMPILE_LINT_CHECKS_TASK,              task -> task.dependsOn(globalScope.getLocalCustomLintChecks()));      // Create top level test tasks.      createTopLevelTestTasks();      // 重点,遍历VariantCreate tasks for all variants (main and tests)      for (ComponentInfo<VariantT, VariantPropertiesT> variant : variants) {          createTasksForVariant(variant, variants);      }      // Test相干的Task      for (ComponentInfo<              TestComponentImpl<? extends TestComponentPropertiesImpl>,              TestComponentPropertiesImpl>              testComponent : testComponents) {          createTasksForTest(testComponent);      }      // 信息记录相干的Task      createReportTasks();  }  

外面仍然注册了很多 Task,Lint、测试和信息记录相干的 Task等。

其中最重要的还是获取在下面创立好的的 Variant,遍历执行 createTasksForVariant 办法,咱们看看它为每一个 Variant 注册了哪些办法:

private void createTasksForVariant(          @NonNull ComponentInfo<VariantT, VariantPropertiesT> variant,          @NonNull List<ComponentInfo<VariantT, VariantPropertiesT>> variants) {      // ... 省略      createAssembleTask(variantProperties);      if (variantType.isBaseModule()) {          createBundleTask(variantProperties);      }      doCreateTasksForVariant(variant, variants);  }  

大家对 createAssembleTask 这个办法必定很相熟,因为咱们每次打包都是应用的 assembleDebug 或者 assembleRelease 这样的命令,这个办法就是创立 Assemble 对应的 Task。

doCreateTasksForVariant 办法就是创立跟 Variant 相干 Task 的办法,不过在 TaskManager 中,它是一个形象办法,交给了 ApplicationTaskManager 去实现。

那么它外面到底创立了哪些 Task 呢?往后面翻,前面的图片会通知你!

第八步 TaskManager第二次创立多个Task

第二次创立多个 Task 调用的是 TaskManager#createPostApiTasks 办法,次要跟 ViewBinding、DataBinding 和 Kotlin 编译相干的 Task,感兴趣的能够看一下。

这里就不一一和同学们剖析了,间接看图:

Task过程

简略的解释一下:

蓝色的:Gradle 配置阶段前 createTasksBeforeEvaluate注册的 Task。

橙色:Gradle 配置阶段实现后创立的 Task。

红色:重要的 Task。

箭头:依赖关系(并不是所有)。

当然,我并没有把所有的 Task 都列出来,依赖关系也只把我看见的列出来(代码太多,并没有都浏览)。

如果咱们将下面的图片和之前官网的打包流程图联合起来,发现很多都是能够对应起来的:

1. 后面有 AIDL、Source Code、Resource资源文件这类的解决 Task。

2. 中期有 Class 编译相干、代码混同相干的 Task。

3. 前期又有创立合并 Dex以及打包 Apk 相干的 Task。

而且,Task 之间都有依赖关系(图中并没有展示),比方我通过命令:

./gradlew assembleDebug  

这个命令会调用 assembleDebug 对应的 Task,在此之前,它会执行完后面依赖的 Task,比方资源解决、编译相干、打包生成咱们想要的APK等等。

到这儿,这个源码就剖析的差不多了,回到第二步,BasePlugin 在 apply 办法外面,还执行了 pluginSpecificApply 办法,不过这个办法是一个空办法。


3.总结

这篇文章的目标是心愿大家对 AGP 有一个轮廓,AGP 次要做了什么?

能够发现,AGP 中注册的大部分 Task 都是为了打包服务的,每个小的 Task 都是打包这个流水线的螺丝钉。

如果感觉本文不错,「点赞」是最好的必定!