1. 初识 Sync

咱们一般会把 Sync 了解为 Android Studio 的预备阶段,包含解析工程装备信息、下载长途依靠到本地、更新代码索引等预备工作,当修正 gradle build 文件后,需求重新 Sync 将 Gradle 构建装备信息同步到 IDE,进而使 IDE 的功用及时运用新的构建装备,这些功用包含项意图 Gradle Task 列表展示、依靠信息展示等等。Sync 是 Android Studio 中独有的概念,当经过 Gradle 命令行程序构建 Android 运用时,只会阅历 Gradle 界说的 Initialization、Configuration 和 Execution 生命周期,根本没有 Sync 的概念。Android Studio 的 Sync 阶段涉及到 IDE、Gradle、Plugin 等多个人物,整理清楚这些人物各自的效果和联络,才能明晰了解 Sync 的整体架构,下面别离来介绍这些人物:

深入理解 Android Studio Sync 流程

IDE层面:Android Studio 根据 IntelliJ IDEA 扩展而来,复用了 IntelliJ IDEA 强壮的代码编辑器和开发者东西等 IDE 根底才能,在此之上 Android Studio 供给了更多进步 Android 构建功率的功用,如 Android 模拟器、代码模版等等。别的 Android Studio 也将自身专业的 Android 运用开发才能反哺给 IntelliJ IDEA,以 Android IDEA Plugin 的形式,使 IntelliJ IDEA 支撑 Android 运用开发,二者相互赋能,相辅相成。

Gradle层面:Gradle 是一个灵敏而强壮的开源构建体系,它除了供给跨平台的可履行程序支撑命令行履行 Gradle 构建外,还专门供给了 Gradle Tooling API 编程 SDK,供外部更方便、更紧密的将 Gradle 构建才能嵌入到 IDE 中,IntelliJ IDEA、Eclipse、VSCode 等 IDE 都采用了这种办法。在 Gradle 源码中也有专门服务于 IntelliJ IDEA、Eclipse 等 IDE 的代码模块,构建东西和 IDE 两个人物之间同样是相互赋能,强强联合。

Plugin 层面:Plugin 层面包含 Android IDEA Plugin 和 Android Gradle Plugin,Android IDEA Plugin 为 IntelliJ IDEA/Android Studio 拓宽了 Android 运用开发才能;Android Gradle Plugin 为 Gradle 拓宽了 Android 运用构建才能。谷歌经过这两个 Plugin 将现代老练优秀的 IDE 开发才能和构建东西联合在一起为 Android 所用,比较于早期 Eclipse 加 ANT 构建的开发办法,大幅提高了 Android 运用开发功率和体验。

2. Sync 流程剖析

了解了 Sync 阶段涉及到的人物以及它们之间的关系后,接下来深化 Android Studio 源码,从代码层面整理清楚 Sync 的要害流程。

2.1 Android Studio 源码剖析

2.1.1 功用进口及预备

在 Android Studio 中触发 Sync 操作后,会从最上层的进口类 GradleSyncInvoker 调用到实际担任解析 Gradle 构建信息的 GradleProjectResolver,调用链如下图所示:

深入理解 Android Studio Sync 流程

调用过程中涉及到的要害类:

  • GradleSyncInvoker:触发 Sync 的进口类,在 Android Studio 多处需求履行 Sync 的当地,都是经过调用此类的 requestProjectSync 办法来触发的

  • ExternalSystemUtil:GradleSyncInvoker、GradleSyncExecutor 等类是专门针对 Sync 功用的封装,Sync 是 Android Studio 中独有的操作,在 IntelliJ IDEA 中并没有 Sync 的概念,IntelliJ IDEA 经过 [Reload All Gradle Projects] 操作来触发解析工程的 Gradle 构建信息,直接从 ExternalSystemUtil 类开端履行

  • GradleProjectResolver:担任具体履行 Sync,其间 resolveProjectInfo 办法是具体履行 Sync 逻辑的当地,该办法的界说如下:

    publicDataNode<ProjectData>resolveProjectInfo(
    @NotNullExternalSystemTaskIdid,
    @NotNullStringprojectPath,
    booleanisPreviewMode,
    @NullableSsettings,
    @NotNullExternalSystemTaskNotificationListenerlistener)
    throwsExternalSystemException,IllegalArgumentException,IllegalStateException
    
  • id:本次 Sync 操作的唯一标识,后续可经过调用 GradleProjectResolver 中的 cancelTask 办法撤销本次 Sync 任务

  • projectPath:工程绝对路径

  • settings:Sync 工程的装备参数,可设置 Java 版别等

  • listener:用于监听此次 Sync 的过程及结果

  • isPreviewMode:是否要启用预览形式,Android Studio 首次打开不知道来历项目时,会让开发者选择项意图打开办法,如下图,若选择 [Stay in Safe Mode] 则会以“预览形式”运转项目,表明 IDE 仅能够阅读项意图源代码,不会履行或解析任何构建任务和脚本

深入理解 Android Studio Sync 流程

进入 GradleProjectResolver 的 resolveProjectInfo 办法中后,首要会对预览形式进行处理,如下代码所示,假如是预览形式,则会简略结构出对应的工程数据结构后立马回来,不进行任何的解析行为:

if(isPreviewMode){
StringprojectName=newFile(projectPath).getName();
ProjectDataprojectData=newProjectData(GradleConstants.SYSTEM_ID,projectName,projectPath,projectPath);
DataNode<ProjectData>projectDataNode=newDataNode<>(ProjectKeys.PROJECT,projectData,null);
......
returnprojectDataNode;
}

运用 Android Studio/IntelliJ IDEA 打开工程时,除了指定工程地点根目录,还能够指定 Gradle 装备文件,这个逻辑在源码中也有所表现:

if(projectPathFile.isFile()&&projectPath.endsWith(GradleConstants.EXTENSION)&&projectPathFile.getParent()!=null){
projectDir=projectPathFile.getParent();
if(settings!=null){
List<String>arguments=settings.getArguments();
if(!arguments.contains("-b")&&!arguments.contains("--build-file")){
settings.withArguments("-b",projectPath);
}
}
}else{
projectDir=projectPath;
}

能够看到假如打开的不是工程根目录而是装备文件,那就会把该装备文件地点的目录作为工程路径,而且会经过 –build-file 参数来指定装备文件,后续会传入到 Gradle 中。对工程初步处理后,接着经过 Gradle Tooling API 获取工程的 BuildEnvironment:

ModelBuilder<BuildEnvironment>modelBuilder=connection.model(BuildEnvironment.class);

调用 Gradle Tooling API 时其内部会自动下载项目装备版别的 Gradle,也便是说,上面代码中获取 BuildEnvironment Model 的调用自身确保了 Gradle 的下载,即将 /grade/wrapper/gradle-wrapper.properties 里 distributionUrl 指定的 Gradle 下载到 GRADLE_HOME/wrapper/dists 下。

BuildEnvironment 是 Gradle 供给的 Gradle Model,Gradle Model 是一个非常重要的概念,当 IDE 经过 Gradle Tooling API 和 Gradle 交互时,传输的便是各式各样的 Model,比方 Gradle 自带的 GradleProject BuildEnvironment 等,别的也能够在 Gradle Plugin 中经过 ToolingModelBuilderRegistry 注册自界说的 Model,如 Android Gradle Plugin 中注册了 AndroidProject Model,那就能够经过 Gradle Tooling API 获取 Android 项目特有的 AndroidProject Model,然后获取由 Android Gradle Plugin 供给的 Android 运用相关工程信息。

2.1.2 装备 BuildAction

持续剖析 Android Studio Sync 源码,接下来结构了一个 ProjectImportAction,它完成了 Gradle Tooling API 中的 BuildAction 接口,BuildAction 界说如下:

/**
*AnactionthatexecutesagainstaGradlebuildandproducesaresultoftype{@codeT}.
*@param<T>Thetypeofresultproducedbythisaction.
*/
publicinterfaceBuildAction<T>extendsSerializable{
Texecute(BuildControllercontroller);
}

BuildAction 是即将传入到 Gradle 构建进程中履行的行为,而且可将结果数据序列化回来给调用方。这个 BuildAction至关重要,它是实际和 Gradle 通讯的当地,其间完成了组织生成工程信息、下载依靠等功用,是 Sync 流程中的核心逻辑。BuildAction 再合作 Gradle Tooling API 中的 BuildActionExecuter,就能够将 BuildAction 交由 Gradle 触发履行了,在履行之前,需先经过 BuildActionExecuter 装备 JVM 参数、Gradle 命令行参数以及环境变量等构建信息:

privatestaticvoidconfigureExecutionArgumentsAndVmOptions(@NotNullGradleExecutionSettingsexecutionSettings,
@NotNullDefaultProjectResolverContextresolverCtx,
booleanisBuildSrcProject){
executionSettings.withArgument("-Didea.sync.active=true");
if(resolverCtx.isResolveModulePerSourceSet()){
executionSettings.withArgument("-Didea.resolveSourceSetDependencies=true");
}
if(!isBuildSrcProject){
for(GradleBuildParticipantbuildParticipant:executionSettings.getExecutionWorkspace().getBuildParticipants()){
executionSettings.withArguments(GradleConstants.INCLUDE_BUILD_CMD_OPTION,buildParticipant.getProjectPath());
}
}
GradleImportCustomizerimportCustomizer=GradleImportCustomizer.get();
GradleProjectResolverUtil.createProjectResolvers(resolverCtx).forEachOrdered(extension->{
if(importCustomizer==null||importCustomizer.useExtraJvmArgs()){
//collectextraJVMargumentsprovidedbygradleprojectresolverextensions
ParametersListparametersList=newParametersList();
for(Pair<String,String>jvmArg:extension.getExtraJvmArgs()){
parametersList.addProperty(jvmArg.first,jvmArg.second);
}
executionSettings.withVmOptions(parametersList.getParameters());
}
//collectextracommand-linearguments
executionSettings.withArguments(extension.getExtraCommandLineArgs());
});
}

上述代码较多,咱们先只重视于 GradleExecutionSettings 的 withArgument 和 withVmOptions 办法,它们别离担任搜集 Gradle 命令行参数和 JVM 参数。从代码中能够看出,这些 Gradle 命令行参数及 JVM 参数大多数是从 extension 中搜集而来,这里的 extension 是指 IntelliJ IDEA Plugin 中的扩展,和扩展点结合运用,可扩展 IntelliJ IDEA 平台特性或其他 IntelliJ IDEA Plugin 的功用特性,举个例子,Gradle IDEA Plugin 供给了工程解析的扩展点:

<extensionPoint
qualifiedName="org.jetbrains.plugins.gradle.projectResolve"
interface="org.jetbrains.plugins.gradle.service.project.GradleProjectResolverExtension"/>

Android IDEA Plugin 中完成了此扩展点,供给了 Android 工程解析的拓宽:

<extensionsdefaultExtensionNs="org.jetbrains.plugins.gradle">
<projectResolveimplementation=
"com.android.tools.idea.gradle.project.sync.idea.AndroidGradleProjectResolver"
order="first"/>
......
</extensions>

接着来看 BuildAction 的参数装备逻辑,终究设置 JVM 参数的当地在 GradleExecutionHelper 的 prepare 办法中:

List<String>jvmArgs=settings.getJvmArguments();
BuildEnvironmentbuildEnvironment=getBuildEnvironment(connection,id,listener,(CancellationToken)null,settings);
if(!jvmArgs.isEmpty()){
//mergegradleargse.g.definedingradle.properties
Collection<String>merged;
if(buildEnvironment!=null){
//theBuildEnvironmentjvmargumentsofthemainbuildshouldbeusedforthe'buildSrc'import
//toavoidspawningofthesecondgradledaemon
BuildIdentifierbuildIdentifier=getBuildIdentifier(buildEnvironment);
List<String>buildJvmArguments=buildIdentifier==null||"buildSrc".equals(buildIdentifier.getRootDir().getName())
?ContainerUtil.emptyList()
:buildEnvironment.getJava().getJvmArguments();
merged=mergeBuildJvmArguments(buildJvmArguments,jvmArgs);
}else{
merged=jvmArgs;
}
List<String>filteredArgs=ContainerUtil.mapNotNull(merged,s->StringUtil.isEmpty(s)?null:s);
operation.setJvmArguments(ArrayUtilRt.toStringArray(filteredArgs));
}

如上代码所示,JVM 参数的装备逻辑很简略:将之前从一系列 GradleProjectResolve 扩展中搜集的、存放在 GradleExecutionSettings 中的 JVM 参数和 BuildEnvironment 中的 JVM 参数合并,然后调用 BuildActionExecuter 的 setJvmArguments 办法,将 JVM 参数设置给 BuildAction。Gradle 命令行参数同样是在 GradleExecutionHelper 的 prepare 办法中装备:

...
List<String>filteredArgs=newArrayList<>();
if(!settings.getArguments().isEmpty()){
StringloggableArgs=StringUtil.join(obfuscatePasswordParameters(settings.getArguments()),"");
LOG.info("Passingcommand-lineargstoGradleToolingAPI:"+loggableArgs);
//filternullsandemptystrings
filteredArgs.addAll(ContainerUtil.mapNotNull(settings.getArguments(),s->StringUtil.isEmpty(s)?null:s));
...
}
filteredArgs.add("-Didea.active=true");
filteredArgs.add("-Didea.version="+getIdeaVersion());
operation.withArguments(ArrayUtilRt.toStringArray(filteredArgs));

关于一个最简略的 Kotlin App Demo 工程,Gradle 命令行参数如下:

来历 参数
Android Studio 源码 –init-script /private/var/folders/_4/j3fdr4nd0x7cf17yvt20f5c00000gp/T/ijmapper.gradle -Didea.sync.active=true -Didea.resolveSourceSetDependencies=true -Porg.gradle.kotlin.dsl.provider.cid=676307056703202 -Pkotlin.mpp.enableIntransitiveMetadataConfiguration=true –init-script/private/var/folders/_4/j3fdr4nd0x7cf17yvt20f5c00000gp/T/ijinit3.gradle -Didea.active=true -Didea.version=2021.3
Android IDEA Plugin 扩展:com.android.tools.idea.gradle.project.sync.idea.AndroidGradleProjectResolver –init-script /private/var/folders/_4/j3fdr4nd0x7cf17yvt20f5c00000gp/T/sync.studio.tooling4770.gradle -Djava.awt.headless=true –stacktrace-Pandroid.injected.build.model.only=true -Pandroid.injected.build.model.only.advanced=true -Pandroid.injected.invoked.from.ide=true -Pandroid.injected.build.model.only.versioned=3 -Pandroid.injected.studio.version=10.4.2 -Pandroid.injected.build.model.disable.src.download=true -Pidea.gradle.do.not.build.tasks=true
Kotlin IDEA Plugin 扩展:org.jetbrains.kotlin.idea.gradleJava.scripting.importing.KotlinDslScriptModelResolver -Dorg.gradle.kotlin.dsl.provider.mode=classpath
Kotlin IDEA Plugin 扩展:org.jetbrains.kotlin.idea.gradleJava.scripting.importing.KotlinDslScriptModelResolver -Porg.gradle.kotlin.dsl.provider.cid=676307056703202
Kotlin IDEA Plugin 扩展:org.jetbrains.kotlin.idea.gradleJava.configuration.KotlinMPPGradleProjectResolver -Pkotlin.mpp.enableIntransitiveMetadataConfiguration=true

要点重视其间的 –init-script 命令行参数,它能够指定一个初始化脚本,初始化脚本会在项目构建脚本之前履行。初始化脚本是 Gradle 供给的一个非常灵敏的机制,除了命令行装备,还能够将初始化脚本命名为 init.gradle 放置到 USER_HOME/.gradle/ 下进行装备。初始化脚本允许自界说所有项意图构建逻辑,比方界说特定机器上所有项意图 JDK 路径等环境信息。在上述 Kotlin App Demo 工程中,Android IDEA Plugin 扩展装备了一个初始化脚本,内容如下:

initscript{
dependencies{
classpathfiles([mapPath('/Users/bytedance/IDE/intellij-community/out/production/intellij.android.gradle-tooling'),mapPath('/Users/bytedance/IDE/intellij-community/out/production/intellij.android.gradle-tooling.impl'),mapPath('/Users/bytedance/.m2/repository/org/jetbrains/kotlin/kotlin-stdlib/1.5.10-release-945/kotlin-stdlib-1.5.10-release-945.jar')])
}
}
allprojects{
applyplugin:com.android.ide.gradle.model.builder.AndroidStudioToolingPlugin
}

初始化脚本中对所有项目运用了 AndroidStudioToolingPlugin 插件,此插件中经过 ToolingModelBuilderRegistry 注册了 AdditionalClassifierArtifactsModel,这个 Gradle Model 中完成了下载依靠 sources 和 javadoc 的功用:

/**
*ModelBuilderfor[AdditionalClassifierArtifactsModel].
*
*Thismodelbuilderdownloadssourcesandjavadocforcomponentsspecifiesinparameter,andreturnsmodel
*[AdditionalClassifierArtifactsModel],whichcontainsthelocationsofdownloadedjarfiles.
*/
classAdditionalClassifierArtifactsModelBuilder:ParameterizedToolingModelBuilder<AdditionalClassifierArtifactsModelParameter>{
...

也便是说,Android IDEA Plugin 供给了依靠 sources 和 javadoc 的下载功用,当经过 Gradle Tooling API 获取 AdditionalClassifierArtifactsModel Gradle Model 的时分,会触发依靠的 sources 和 javadoc 下载。

剖析完 BuildAction 的 JVM 参数和 Gradle 命令行参数装备流程后,最终来看 BuildAction 环境变量的装备,终究装备的当地在 GradleExecutionHelper 的 setupEnvironment 办法中:

GeneralCommandLinecommandLine=newGeneralCommandLine();
commandLine.withEnvironment(settings.getEnv());
commandLine.withParentEnvironmentType(
settings.isPassParentEnvs()?GeneralCommandLine.ParentEnvironmentType.CONSOLE:GeneralCommandLine.ParentEnvironmentType.NONE);
Map<String,String>effectiveEnvironment=commandLine.getEffectiveEnvironment();
operation.setEnvironmentVariables(effectiveEnvironment);

GeneralCommandLine 中包含当前 Java 进程所有的环境变量,其他环境变量和 JVM 参数类似都被搜集在 GradleExecutionSettings 中,Android Studio 会先将其他环境变量与 GeneralCommandLine 中的环境变量合并,然后装备给 BuildAction. 关于不进行任何装备的默许 sync 行为,GradleExecutionSettings 中环境变量为空,全由 GeneralCommandLine 供给。

2.1.3 履行 BuildAction

剖析完 BuildAction 的装备逻辑后,接着来看 BuildAction 中具体做了哪些事。BuildAction 中的行为不再处于 Android Studio IDE 进程了,而是在 Gradle 构建进程中履行。IDE 经过 Gradle Tooling API 与 Gradle 交互时,首要前言是 Gradle Model,BuildAction 中也不例外。BuildAction 的具体履行逻辑见其完成类 ProjectImportAction 中的 execute 办法,咱们只重视此办法中与 Gradle Model 相关的代码:

publicAllModelsexecute(finalBuildControllercontroller){
...
fetchProjectBuildModels(wrappedController,isProjectsLoadedAction,myGradleBuild);
addBuildModels(wrappedController,myAllModels,myGradleBuild,isProjectsLoadedAction);
...
}

BuildAction 中调用 fetchProjectBuildModels 和 addBuildModels 办法获取 Gradle Model。先来剖析 fetchProjectBuildModels 办法,该办法中进一步调用 getProjectModels 办法:

privateList<Runnable>getProjectModels(@NotNullBuildControllercontroller,
@NotNullfinalAllModelsallModels,
@NotNullfinalBasicGradleProjectproject,
booleanisProjectsLoadedAction){
...
Set<ProjectImportModelProvider>modelProviders=getModelProviders(isProjectsLoadedAction);
for(ProjectImportModelProviderextension:modelProviders){
extension.populateProjectModels(controller,project,modelConsumer);
}
...
}

如上代码所示,经过 ProjectImportModelProvider 的 populateProjectModels 办法进一步去获取 Gradle Model。BuildAction 的 addBuildModels 办法与此十分相似:

privatevoidaddBuildModels(@NotNullfinalToolingSerializerAdapterserializerAdapter,
@NotNullBuildControllercontroller,
@NotNullfinalAllModelsallModels,
@NotNullfinalGradleBuildbuildModel,
booleanisProjectsLoadedAction){
Set<ProjectImportModelProvider>modelProviders=getModelProviders(isProjectsLoadedAction);
for(ProjectImportModelProviderextension:modelProviders){
extension.populateBuildModels(controller,buildModel,modelConsumer);
}
...
}

能够看到同样是交给了 ProjectImportModelProvider 去获取 Gradle Model,不同的是,前者调用的 populateProjectModels,此处调用的是 populateBuildModels 办法,ProjectImportModelProvider 的效果便是生成 Gradle Model。ProjectImportModelProvider 同 JVM 参数和 Gradle 命令行参数一样,都是由一系列 Gradle IDEA Plugin 扩展供给,如下代码所示:

for(GradleProjectResolverExtensionresolverExtension=tracedResolverChain;
resolverExtension!=null;
resolverExtension=resolverExtension.getNext()){
...
ProjectImportModelProvidermodelProvider=resolverExtension.getModelProvider();
if(modelProvider!=null){
projectImportAction.addProjectImportModelProvider(modelProvider);
}
ProjectImportModelProviderprojectsLoadedModelProvider=resolverExtension.getProjectsLoadedModelProvider();
if(projectsLoadedModelProvider!=null){
projectImportAction.addProjectImportModelProvider(projectsLoadedModelProvider,true);
}
}

关于 Android 工程来说,要点重视 Android IDEA Plugin,它供给的 ProjectImportModelProvider 的完成类为 AndroidExtraModelProvider,该完成类的 populateProjectModels 办法如下:

overridefunpopulateProjectModels(controller:BuildController,
projectModel:Model,
modelConsumer:ProjectImportModelProvider.ProjectModelConsumer){
controller.findModel(projectModel,GradlePluginModel::class.java)
?.also{pluginModel->modelConsumer.consume(pluginModel,GradlePluginModel::class.java)}
controller.findModel(projectModel,KaptGradleModel::class.java)
?.also{model->modelConsumer.consume(model,KaptGradleModel::class.java)}
}

此办法中经过 Gradle Tooling API 获取了 GradlePluginModel 和 KaptGradleModel 两个 Gradle Model,GradlePluginModel 中供给了项目已运用的 Gradle Plugin 信息;KaptGradleModel 供给了 Kotlin 注解处理相关信息。接着来看 populateBuildModels 办法:

overridefunpopulateBuildModels(
controller:BuildController,
buildModel:GradleBuild,
consumer:ProjectImportModelProvider.BuildModelConsumer){
populateAndroidModels(controller,buildModel,consumer)
populateProjectSyncIssues(controller,buildModel,consumer)
}

其间别离调用了 populateAndroidModels 和 populateProjectSyncIssues 办法,先来看 populateProjectSyncIssues 办法,它会进一步经过 Gradle Tooling API 获取 ProjectSyncIssues Gradle Model,用于搜集 Sync 过程中出现的问题。再来剖析 populateAndroidModels 办法,它在整个 Sync 过程中至关重要,其间经过 Gradle Tooling API 获取了 Android 工程相关的 Gradle Model:

valandroidModules:MutableList<AndroidModule>=mutableListOf()
buildModel.projects.forEach{gradleProject->
findParameterizedAndroidModel(controller,gradleProject,AndroidProject::class.java)?.also{androidProject->
consumer.consumeProjectModel(gradleProject,androidProject,AndroidProject::class.java)
valnativeAndroidProject=findParameterizedAndroidModel(controller,gradleProject,NativeAndroidProject::class.java)?.also{
consumer.consumeProjectModel(gradleProject,it,NativeAndroidProject::class.java)
}
androidModules.add(AndroidModule(gradleProject,androidProject,nativeAndroidProject))
}
}

如上代码所示,别离获取了由 Android Gradle Plugin 注册的两个 Gradle Model AndroidProject 和 NativeAndroidProject,AndroidProject 中包含 Android 运用的 BuildType、Flavors、Variant、Dependency 等要害信息;NativeAndroidProject 中包含 NDK、NativeToolchain 等 Android C/C++ 项目相关信息。获取了最要害的 AndroidProject 和 NativeAndroidProject 后,接着是对单 Variant Sync 的处理:

if(syncActionOptions.isSingleVariantSyncEnabled){
chooseSelectedVariants(controller,androidModules,syncActionOptions)
}

怎么了解单 Variant Sync 呢?Variant 指 Android 运用的产物变体,比方最简略的 Debug 和 Release 版别运用包。Variant 对应于一套构建装备,与项目源码结构、依靠列表相关联。Android 运用或许有多个 Variant,假如在 Sync 时结构所有 Variant,整体耗时或许极长,所以 Android Studio Sync 默许只会结构一个 Variant,并支撑 Variant 切换功用。假如启用了单 Variant Sync,前面获取 AndroidProject 时会传入过滤参数,奉告 Android Gradle Plugin 结构 AndroidProject 时无需结构 Variant 信息。

2.2 Sync 流程整理

2.2.1 Android Studio 视角

Android Studio Sync 流程的源码巨大而繁杂,本文侧重剖析了从触发 Sync 进口到 Gradle 构建完毕的阶段,后续还有对 Gradle 数据的处理,以及言语才能模块根据 Gradle 数据进行代码索引的流程,而言语才能又是一个大型而杂乱的模块,本文就不再持续展开。

上文源码剖析部分将触发 Sync 进口到 Gradle 构建完毕划分为 Sync 功用进口及预备、装备 BuildAction 以及履行 BuildAction,整体流程如下图所示:

深入理解 Android Studio Sync 流程

2.2.2 Gradle 视角

上面都是以 IDE 视角去剖析 Android Studio Sync,整体流程较杂乱,接下来以 Gradle 视角去整理 Sync 流程,侧重重视 Gradle 侧的行为:

深入理解 Android Studio Sync 流程

如上图,关于 Gradle 来说,Sync 流程中 Android Studio 会经过 Gradle Tooling API 从 Gradle 侧获取一系列所需的 Gradle Model,除 Gradle 自身外,Gradle Plugin 也能够供给自界说的 Gradle Model。别的 Sync 流程中 Gradle 会阅历自身界说的生命周期,聚集此视角整理流程如下:

深入理解 Android Studio Sync 流程

当经过 BuildAction 获取 Gradle Model 时会触发 Gradle 的构建行为,Gradle 构建会阅历自身生命周期界说的 Initialization、Configuration 和 Execution 阶段。

3. 总结

本文首要介绍了 Android Studio Sync 流程中各个人物的效果及联络,对 Sync 有一个较明晰的整体认识,然后从源码视点深化剖析从触发 Sync 进口到 Gradle 构建完毕的阶段,并具体解释了 Gradle Model、BuildAction 等要害概念,最终别离从 Android Studio 视角和 Gradle 视角对 Sync 流程进行了整体整理。

经过对 Android Studio Sync 流程的深化剖析,除了对 Sync 功用的完成原理深度掌握外,对其意义也有了更深的了解。Sync 是 Android Studio 界说的一个 IDE 预备阶段,在这个预备阶段中,需提早预备好要害的 IDE 功用,而这些功用要到达可用状态,需求获取其必需的数据。根据这个视点,对 Sync 流程的优化方向也有了必定启示:首要从产品层面出发考虑 Sync 阶段的界说,不是开发者真正必需的功用都能够考虑省略或延后预备;然后承认必需功用所需的最小数据集,不必需的数据都能够省略;最终针对必需数据,经过更高效的完成或缓存,找到最快的获取办法。

4.参阅链接

mp.weixin.qq.com/s/cftj6Wueo…

developer.android.com/studio/intr…

android.googlesource.com/platform/to…

plugins.jetbrains.com/developers

5. 关于咱们

咱们是字节跳动终端技术团队(Client Infrastructure)下的 Developer Tools 团队,担任打造公司范围内,面向不同事务场景的研制东西,提高移动运用研制功率。目前急需寻觅 Android 移动研制工程师 / iOS 移动研制工程师 / 服务端研制工程师。了解更多信息请联络:wangyinghao.ahab@bytedance.com,邮件主题 简历-姓名-求职意向-希望城市-电话。