欧美vvv,亚洲第一成人在线,亚洲成人欧美日韩在线观看,日本猛少妇猛色XXXXX猛叫

新聞資訊

    . 初識 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 的整體架構,下面分別來介紹這些角色:

    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,調用鏈如下圖所示:

    調用過程中涉及到的關鍵類:

    • 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 邏輯的地方,該方法的定義如下:
    public DataNode<ProjectData> resolveProjectInfo(
        @NotNull ExternalSystemTaskId id,
        @NotNull String projectPath,
        boolean isPreviewMode,
        @Nullable S settings,
        @NotNull ExternalSystemTaskNotificationListener listener)
      throws ExternalSystemException, IllegalArgumentException, IllegalStateException
    
    • id:本次 Sync 操作的唯一標識,后續可通過調用 GradleProjectResolver 中的 cancelTask 方法取消本次 Sync 任務
    • projectPath:工程絕對路徑
    • settings:Sync 工程的配置參數,可設置 Java 版本等
    • listener:用于監聽此次 Sync 的過程及結果
    • isPreviewMode:是否要啟用預覽模式,Android Studio 首次打開未知來源項目時,會讓開發者選擇項目的打開方式,如下圖,若選擇 [Stay in Safe Mode] 則會以“預覽模式”運行項目,表示 IDE 僅可以瀏覽項目的源代碼,不會執行或解析任何構建任務和腳本

    進入 GradleProjectResolver 的 resolveProjectInfo 方法中后,首先會對預覽模式進行處理,如下代碼所示,如果是預覽模式,則會簡單構造出對應的工程數據結構后立馬返回,不進行任何的解析行為:

    if (isPreviewMode) {
      String projectName=new File(projectPath).getName();
      ProjectData projectData=new ProjectData(GradleConstants.SYSTEM_ID, projectName, projectPath, projectPath);
      DataNode<ProjectData> projectDataNode=new DataNode<>(ProjectKeys.PROJECT, projectData, null);
      ......
      return projectDataNode;
    }
    

    使用 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 定義如下:

     /**
    * An action that executes against a Gradle build and produces a result of type {  @code  T}.
     *  @param <T> The type of result produced by this action.
    */
    public interface BuildAction<T> extends Serializable {
    
    T execute(BuildController controller);
    }
    

    BuildAction 是即將傳入到 Gradle 構建進程中執行的行為,并且可將結果數據序列化返回給調用方。這個 BuildAction至關重要,它是實際和 Gradle 通信的地方,其中實現了組織生成工程信息、下載依賴等功能,是 Sync 流程中的核心邏輯。BuildAction 再配合 Gradle Tooling API 中的 BuildActionExecuter,就可以將 BuildAction 交由 Gradle 觸發執行了,在執行之前,需先通過 BuildActionExecuter 配置 JVM 參數、Gradle 命令行參數以及環境變量等構建信息:

    private static void configureExecutionArgumentsAndVmOptions(@NotNull GradleExecutionSettings executionSettings,
                                                                @NotNull DefaultProjectResolverContext resolverCtx,
                                                                boolean isBuildSrcProject) {
      executionSettings.withArgument("-Didea.sync.active=true");
      if (resolverCtx.isResolveModulePerSourceSet()) {
        executionSettings.withArgument("-Didea.resolveSourceSetDependencies=true");
      }
      if (!isBuildSrcProject) {
        for (GradleBuildParticipant buildParticipant : executionSettings.getExecutionWorkspace().getBuildParticipants()) {
          executionSettings.withArguments(GradleConstants.INCLUDE_BUILD_CMD_OPTION, buildParticipant.getProjectPath());
        }
      }
      GradleImportCustomizer importCustomizer=GradleImportCustomizer.get();
      GradleProjectResolverUtil.createProjectResolvers(resolverCtx).forEachOrdered(extension -> {
        if (importCustomizer==null || importCustomizer.useExtraJvmArgs()) {
          // collect extra JVM arguments provided by gradle project resolver extensions
          ParametersList parametersList=new ParametersList();
          for (Pair<String, String> jvmArg : extension.getExtraJvmArgs()) {
            parametersList.addProperty(jvmArg.first, jvmArg.second);
          }
          executionSettings.withVmOptions(parametersList.getParameters());
        }
        // collect extra command-line arguments
        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 工程解析的拓展:

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

    接著來看 BuildAction 的參數配置邏輯,最終設置 JVM 參數的地方在 GradleExecutionHelper 的 prepare 方法中:

    List<String> jvmArgs=settings.getJvmArguments();
    BuildEnvironment buildEnvironment=getBuildEnvironment(connection, id, listener, (CancellationToken)null, settings);
    if (!jvmArgs.isEmpty()) {
      // merge gradle args e.g. defined in gradle.properties
      Collection<String> merged;
      if (buildEnvironment !=null) {
        // the BuildEnvironment jvm arguments of the main build should be used for the 'buildSrc' import
        // to avoid spawning of the second gradle daemon
        BuildIdentifier buildIdentifier=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=new ArrayList<>();
    if (!settings.getArguments().isEmpty()) {
      String loggableArgs=StringUtil.join(obfuscatePasswordParameters(settings.getArguments()), " ");
      LOG.info("Passing command-line args to Gradle Tooling API: " + loggableArgs);
      // filter nulls and empty strings
      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 {
            classpath files([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 {
        apply plugin: com.android.ide.gradle.model.builder.AndroidStudioToolingPlugin
    }
    

    初始化腳本中對所有項目應用了 AndroidStudioToolingPlugin 插件,此插件中通過 ToolingModelBuilderRegistry 注冊了 AdditionalClassifierArtifactsModel,這個 Gradle Model 中實現了下載依賴 sources 和 javadoc 的功能:

     /**
    * Model Builder for [AdditionalClassifierArtifactsModel].
    *
    * This model builder downloads sources and javadoc for components specifies in parameter, and returns model
    * [AdditionalClassifierArtifactsModel], which contains the locations of downloaded jar files.
    */
    class AdditionalClassifierArtifactsModelBuilder : ParameterizedToolingModelBuilder<AdditionalClassifierArtifactsModelParameter> {
    ...
    

    也就是說,Android IDEA Plugin 提供了依賴 sources 和 javadoc 的下載功能,當通過 Gradle Tooling API 獲取 AdditionalClassifierArtifactsModel Gradle Model 的時候,會觸發依賴的 sources 和 javadoc 下載。

    分析完 BuildAction 的 JVM 參數和 Gradle 命令行參數配置流程后,最后來看 BuildAction 環境變量的配置,最終配置的地方在 GradleExecutionHelper 的 setupEnvironment 方法中:

    GeneralCommandLine commandLine=new GeneralCommandLine();
    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 相關的代碼:

    public AllModels execute(final BuildController controller) {
      ...
      fetchProjectBuildModels(wrappedController, isProjectsLoadedAction, myGradleBuild);
      addBuildModels(wrappedController, myAllModels, myGradleBuild, isProjectsLoadedAction);
      ...
    }
    

    BuildAction 中調用 fetchProjectBuildModels 和 addBuildModels 方法獲取 Gradle Model。先來分析 fetchProjectBuildModels 方法,該方法中進一步調用 getProjectModels 方法:

    private List<Runnable> getProjectModels(@NotNull BuildController controller,
                                            @NotNull final AllModels allModels,
                                            @NotNull final BasicGradleProject project,
                                            boolean isProjectsLoadedAction) {
        ...
        Set<ProjectImportModelProvider> modelProviders=getModelProviders(isProjectsLoadedAction);
        for (ProjectImportModelProvider extension : modelProviders) {
          extension.populateProjectModels(controller, project, modelConsumer);
        }
        ...
    }
    

    如上代碼所示,通過 ProjectImportModelProvider 的 populateProjectModels 方法進一步去獲取 Gradle Model。BuildAction 的 addBuildModels 方法與此十分相似:

    private void addBuildModels(@NotNull final ToolingSerializerAdapter serializerAdapter,
                                @NotNull BuildController controller,
                                @NotNull final AllModels allModels,
                                @NotNull final GradleBuild buildModel,
                                boolean isProjectsLoadedAction) {
        Set<ProjectImportModelProvider> modelProviders=getModelProviders(isProjectsLoadedAction);
        for (ProjectImportModelProvider extension : modelProviders) {
          extension.populateBuildModels(controller, buildModel, modelConsumer);
        }
        ...
    }
    

    可以看到同樣是交給了 ProjectImportModelProvider 去獲取 Gradle Model,不同的是,前者調用的 populateProjectModels,此處調用的是 populateBuildModels 方法,ProjectImportModelProvider 的作用就是生成 Gradle Model。ProjectImportModelProvider 同 JVM 參數和 Gradle 命令行參數一樣,都是由一系列 Gradle IDEA Plugin 擴展提供,如下代碼所示:

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

    對于 Android 工程來說,重點關注 Android IDEA Plugin,它提供的 ProjectImportModelProvider 的實現類為 AndroidExtraModelProvider,該實現類的 populateProjectModels 方法如下:

    override fun populateProjectModels(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 方法:

    override fun populateBuildModels(
      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:

      val androidModules: MutableList<AndroidModule>=mutableListOf()
      buildModel.projects.forEach { gradleProject ->
    findParameterizedAndroidModel(controller, gradleProject, AndroidProject::class.java)?.also { androidProject ->
    consumer.consumeProjectModel(gradleProject, androidProject, AndroidProject::class.java)
          val nativeAndroidProject=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,整體流程如下圖所示:

    2.2.2 Gradle 視角

    上面都是以 IDE 視角去分析 Android Studio Sync,整體流程較復雜,接下來以 Gradle 視角去梳理 Sync 流程,著重關注 Gradle 側的行為:

    如上圖,對于 Gradle 來說,Sync 流程中 Android Studio 會通過 Gradle Tooling API 從 Gradle 側獲取一系列所需的 Gradle Model,除 Gradle 自身外,Gradle Plugin 也可以提供自定義的 Gradle Model。另外 Sync 流程中 Gradle 會經歷自身定義的生命周期,聚焦此視角梳理流程如下:

    當通過 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.參考鏈接

    https://mp.weixin.qq.com/s/cftj6WueoHlLh-So9REEXQ

    https://developer.android.com/studio/intro

    https://android.googlesource.com/platform/tools/base/+/studio-master-dev

    https://plugins.jetbrains.com/developers

    5. 關于我們

    我們是字節跳動終端技術團隊(Client Infrastructure)下的 Developer Tools 團隊,負責打造公司范圍內,面向不同業務場景的研發工具,提升移動應用研發效率。目前急需尋找 Android 移動研發工程師 / iOS 移動研發工程師 / 服務端研發工程師。了解更多信息請聯系:wangyinghao.ahab@bytedance.com,郵件主題 簡歷-姓名-求職意向-期望城市-電話。

    注意,啟用talkback以后,操作手勢有變化,先觸摸要點擊的項目半秒鐘,然后雙擊才能激活。翻頁的話得兩個手指滑動。

    提問者評價

    原來是這樣,關機重新啟動,密碼都輸不了,最后硬格了。

    (我是摘抄)

    無法開機的原因很多,請依次檢查:

    1.刷機前WIPE過嗎?如果未WIPE會導致出現反復重啟的問題

    2.刷入的是什么ROM,如果刷的不是三星i9000的版本會導致出現問題的。CM、力卓的ROM都是挺不錯的

    能震動說明你已經能夠跳過recovery進入到系統啟動步驟了。你可以扣下電池,然后按音量上+下+開機來進入recovery

    如果沒刷recovery(例如用ODIN刷機包)。那么只能進入挖煤用ODIN重刷了

    2

    二、第二個手機usb連不上電腦的解決方法不用安裝任何東西,你把手機連接電腦后,點擊手機設置——應用程序——開發——usb調試打鉤,手機有個“打開usb功能”的提示,點確定就可以了。

    3

    三、在微軟網站上下載MicrosoftActiveSync_setup_cn4.0以上的版本安裝后就可以同步電腦了。你可以用設置里的大容量存儲作U盤連接電腦。

    安裝微軟的同步軟件MicrosoftActiveSync4.5,一般相關的一些連接手機的軟件都需要用這個同步軟件先連接后才能連接,如果你只查看大容量儲存里面的資料你就可以直接用數據線和電腦連接,在手機設置——連接——USB連接模式——選擇大容量儲存——確定就完成了。

網站首頁   |    關于我們   |    公司新聞   |    產品方案   |    用戶案例   |    售后服務   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區    電話:010-     郵箱:@126.com

備案號:冀ICP備2024067069號-3 北京科技有限公司版權所有