阅读 202

Gradle浅析之生命周期

我们在日常开发中,无论是使用图形构建按钮还是使用命令开启构建任务,其会经历设置,陪着,构建任务依赖图,最终执行我们输入的任务。但是其内部如何进行这一系列过程的,今天我们就分析Android中输入 ./gradlew assembleBuild后, gradle的生命周期原理。

Gradle命令入口

在我们每一个android下面都有一个 gradlew.bat脚本文件,其为我们执行 ./gradlew命令的入口。其最终会执行下面的命令

@rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 复制代码

其最终会调用GradleWrapperMain类,调用其main方法,其为gradle源码中的类。也是我们执行gradlew命令的入口。到这里我们要继续看起源码,必须下载对应的gradle源码。

Gradle源码

我们可以从github下载对应的源码,我这里分析的源码下载的是7.3的。下载下来用Intellij idead编译需要一段时间,后续开启缓存模式构建就快了。

Gradle下载

接下来我们准备好源码,进入GradleMain看起源码。我们开发中知道,如果第一次构建项目其会更加我们项目下的gradle目录下的wrapper.properties进行下载对应的版本,如果本地有其就不会下载,今天我们就探究一下其原理。

  • wrapper.properties配置

distributionBase=GRADLE_USER_HOME distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME 复制代码

GradleWrapperMain

读取wrapper的配置

  • 其首先从我们目录下gradle的配置文件读取配置信息,即上面列出的

  • 然后创建WrapperExeucter

  • 接着执行其ececute,其会传入Install和BootstrapMainStarter

public static void main(String[] args) {    File wrapperJar = wrapperJar();    File propertiesFile = wrapperProperties(wrapperJar);    ....     WrapperExecutor wrapperExecutor = WrapperExecutor.forWrapperPropertiesFile(propertiesFile);    wrapperExecutor.execute(                 args,                 new Install(logger, new Download(logger, "gradlew", UNKNOWN_VERSION), new PathAssembler(gradleUserHome, rootDir)),                 new BootstrapMainStarter());              } 复制代码

WrapperExecuter

其executer方法,内部会首先调用Install对应的方法,去判断是否需要下载Gradle,然后调用bootstrapMainStarter的启动方法

public void execute(String[] args, Install install, BootstrapMainStarter bootstrapMainStarter) throws Exception {         File gradleHome = install.createDist(config);         bootstrapMainStarter.start(args, gradleHome);     } 复制代码

Install配置Gradle

其createDist方法,就是根据配置里的信息去下载对应版本的gradle,如果本地存在,则直接加载缓存。

public File createDist(final WrapperConfiguration configuration)  {         //下载地址 final URI distributionUrl = configuration.getDistribution();        // 文件256校验码 final String distributionSha256Sum = configuration.getDistributionSha256Sum();         //本地对应的配置  final PathAssembler.LocalDistribution localDistribution = pathAssembler.     getDistribution(configuration); final File distDir = localDistribution.getDistributionDir(); final File localZipFile = localDistribution.getZipFile(); ... //是否需要下载,本地文件是否存在     boolean needsDownload = !localZipFile.isFile();                 URI safeDistributionUrl = Download.safeUri(distributionUrl); if (needsDownload) {   File tmpZipFile = new File(localZipFile.getParentFile(),                     localZipFile.getName() + ".part");   tmpZipFile.delete();   logger.log("Downloading " + safeDistributionUrl);   //开始下载   download.download(distributionUrl, tmpZipFile);   tmpZipFile.renameTo(localZipFile); }  ... //校验文件是否下载正确 verifyDownloadChecksum(configuration.getDistribution().toString(),                         localZipFile, distributionSha256Sum);     //解压 unzip(localZipFile, distDir);               }                   复制代码

经过上面的步骤,就按照gradle目录下的配置,下载好对应的gradle版本包,即我们后面整体gradle执行代码。

BootstrapMainStarter开启任务

其start方法,开始gradle的构建流程,其调用流程比较复杂,不同版本代码逻辑有些不同。具体过程不是我们本文的重点,我简单梳理了一个大致调用流程,感兴趣的可以作为参看查看其源码。其最终会调用VintageBuildModelController的doBuildState。

流程图

Gradle 生命周期.jpg 接下来我们分析其生命周期的每个阶段做了什么。

Gradle生命周期

查看对应VintageBuildModelController类State,其主要有四个阶段。

生命周期阶段

private enum Stage implements StateTransitionController.State {         Created,          LoadSettings,          Configure,          ScheduleTasks,          TaskGraph     } 复制代码

�其doBuilldState会根据对应要执行到的阶段,依次调用对应的方法。下面我们依次分析。

LoadSettings

进入doBuildStages会根据传递的状态执行到对应的状态

private void doBuildStages(Stage upTo) {         prepareSettings();         if (upTo == Stage.LoadSettings) {             return;         }         prepareProjects();         if (upTo == Stage.Configure) {             return;         }         prepareTaskGraph();         if (upTo == Stage.ScheduleTasks) {             return;         }         prepareTaskExecution();     } 复制代码

最终执行的为prepareTaskExecution。最初执行的为prepareSetting,对应的周期阶段为LoadtingSetting.

SettingPreparer开启LoadSetting

preparesetting方法内部调用SettingPrepare的preparesetting方法,开始任务,同时执行前,将Stage设置为LoadSetting。

private void prepareSettings() {     controller.transitionIfNotPreviously(Stage.Created, Stage.LoadSettings,       () -> settingsPreparer.prepareSettings(gradle));     } 复制代码

其对应的实现类为DefaultSettingsPreparer,其具体流程如下

  • 判断是否为RootBuild,如果是,从顶层开始,否则从内部开始

  • 然后查找对应的Setting.gradle并加载

  @Override     public void prepareSettings(GradleInternal gradle) {         SettingsLoader settingsLoader = gradle.isRootBuild() ?              settingsLoaderFactory.forTopLevelBuild() :          settingsLoaderFactory.forNestedBuild();         settingsLoader.findAndLoadSettings(gradle);     } 复制代码

我们以RootBuild为例分析,其调用forTopLenvelBuild方法,返回对应的SettingLoader,其类似其他代码,通过逐级代理,预处理任务,最终的SettingLoader为DefaultSettingsLoader�

public SettingsLoader forTopLevelBuild() {         return new GradlePropertiesHandlingSettingsLoader(             new InitScriptHandlingSettingsLoader(                 new CompositeBuildSettingsLoader(                     new ChildBuildRegisteringSettingsLoader(                         new CommandLineIncludedBuildSettingsLoader(                             defaultSettingsLoader()                         ),                         buildRegistry,                         buildIncluder),                     buildRegistry),                 initScriptHandler),             buildLayoutFactory,             gradlePropertiesController         );     } 复制代码

DefalutSeetingLoader查找处理_setting.gradle_

�其类注释说明其功能,定位和处理setting.gradle文件,读取里面配置的Module. 上面最后会调用findAndLoadSettings,我们查看源码,探究其如何定位和处理对应的文件

public SettingsInternal findAndLoadSettings(GradleInternal gradle) {         StartParameter startParameter = gradle.getStartParameter();         //获取构建项目下setting文件或目录         SettingsLocation settingsLocation = buildLayoutFactory.getLayoutFor(new BuildLayoutConfiguration(startParameter));         //根据查找的文件,加载读取内容         SettingsInternal settings = findSettingsAndLoadIfAppropriate(gradle, startParameter, settingsLocation, gradle.getClassLoaderScope());         ProjectSpec spec = ProjectSpecs.forStartParameter(startParameter, settings);         if (useEmptySettings(spec, settings, startParameter)) {             settings = createEmptySettings(gradle, startParameter, settings.getClassLoaderScope());         }         //根据setting项目描述配置rootProjet相关信息          setDefaultProject(spec, settings);         return settings;     } 复制代码

定位setting文件

其首先获取我们项目整体目录,然后在其目录下获取setting.gradle文件

  • 构建项目是否使用空setting结构,如是则直接返回空

  • 获取目录下setting文件

  • 如果存在检测是否为文件,否则抛出异常

  • 如果存在则返回对应的Buildlayout

BuildLayout会保护具体文件的地址信息

public BuildLayout getLayoutFor(BuildLayoutConfiguration configuration) {         if (configuration.isUseEmptySettings()) {             return buildLayoutFrom(configuration, null);         }         File explicitSettingsFile = configuration.getSettingsFile();         if (explicitSettingsFile != null) {             if (!explicitSettingsFile.isFile()) {                 throw new MissingResourceException(explicitSettingsFile.toURI(), String.format("Could not read settings file '%s' as it does not exist.", explicitSettingsFile.getAbsolutePath()));             }             return buildLayoutFrom(configuration, explicitSettingsFile);         }         return getLayoutFor(configuration.getCurrentDir(), configuration.isSearchUpwards());     } 复制代码

public BuildLayout(File rootDirectory, File settingsDir, @Nullable File settingsFile, ScriptFileResolver scriptFileResolver) {         super(settingsDir, settingsFile);         this.rootDirectory = rootDirectory;         this.scriptFileResolver = scriptFileResolver;     } 复制代码

加载setting.gradle文件

其通过SettingProcessor处理对应的文件,然后返回SettingInternal类

/**      * Finds the settings.gradle for the given startParameter, and loads it if contains the project selected by the      * startParameter, or if the startParameter explicitly specifies a settings script.  If the settings file is not      * loaded (executed), then a null is returned.      */  private SettingsInternal findSettingsAndLoadIfAppropriate(         GradleInternal gradle,         StartParameter startParameter,         SettingsLocation settingsLocation,         ClassLoaderScope classLoaderScope     ) {         SettingsInternal settings = settingsProcessor.process(gradle, settingsLocation, classLoaderScope, startParameter);         validate(settings);         return settings;     } 复制代码

SettingInternal具体实现类为DefalutSetting,其中settingsProcessor有多个实现类,类似上面的处理,其也是逐级嵌套,最终的为**ScriptEvaluatingSettingsProcessor,**我们看起代码 �发现其会加载对应文件里的内容,然后创建SettingsInternal

public SettingsInternal process(GradleInternal gradle,                                     SettingsLocation settingsLocation,                                     ClassLoaderScope baseClassLoaderScope,                                     StartParameter startParameter) {         //统计时间配置         Timer settingsProcessingClock = Time.startTimer();         //解析gradleProperties文件的配置信息         Map<String, String> properties = gradleProperties.mergeProperties(emptyMap());         //解析里面的内容,并加载         TextResourceScriptSource settingsScript = new TextResourceScriptSource(textFileResourceLoader.loadFile("settings file", settingsLocation.getSettingsFile()));         //创建SettingInternal         SettingsInternal settings = settingsFactory.createSettings(gradle, settingsLocation.getSettingsDir(), settingsScript, properties, startParameter, baseClassLoaderScope);         gradle.getBuildListenerBroadcaster().beforeSettings(settings);         applySettingsScript(settingsScript, settings);         LOGGER.debug("Timing: Processing settings took: {}", settingsProcessingClock.getElapsed());         return settings;     } 复制代码

创建Settinginternal
public SettingsInternal createSettings(...){      ClassLoaderScope classLoaderScope = baseClassLoaderScope.createChild("settings[" + gradle.getIdentityPath() + "]");         ScriptHandlerInternal settingsScriptHandler = scriptHandlerFactory.create(settingsScript, classLoaderScope);         DefaultSettings settings = instantiator.newInstance(DefaultSettings.class,             serviceRegistryFactory,             gradle,             classLoaderScope,             baseClassLoaderScope,             settingsScriptHandler,             settingsDir,             settingsScript,             startParameter         );         DynamicObject dynamicObject = ((DynamicObjectAware) settings).getAsDynamicObject();         ((ExtensibleDynamicObject) dynamicObject).addProperties(gradleProperties);         return settings; } 复制代码

总结

到这里LoadSetting就结束了,其主要做了以下工作

  • 查找setting文件

  • 加载解析gradle.properties文件

  • 解析setting文件内容,并创建对应的类:DefalutSetting

Configure

项目配置阶段入口方法为 prepareProjects,与LoadSetting类似,其也有对应的Prepare处理,其为ProjectPrepare

private void prepareProjects() { controller.transitionIfNotPreviously(Stage.LoadSettings, Stage.Configure,   () -> projectsPreparer.prepareProjects(gradle));  } 复制代码

ProjectsPreparer

其方法传入的参数GradleInternal,包含了上一阶段处理完的settings 对象配置,即DefalutSetting. 其对应的实现类为DefalutProjectsPreparer.同样与LoadSetting类似,其也判断是否为RootBuild,同时其也会判断是否配置的后台

 if (buildModelParameters.isConfigureOnDemand() && gradle.isRootBuild()) {             projectConfigurer.configure(gradle.getRootProject());         } else {             projectConfigurer.configureHierarchy(gradle.getRootProject());             new ProjectsEvaluatedNotifier(buildOperationExecutor).notify(gradle);         } 复制代码

无论何种情况,都有ProjectConfigurer处理

TaskPathProjectEvaluator处理Project

ProjectConfigurer的实现类为TaskPathProjectEvaluator。两个方法的区别时,configureHierarchyFully会先配置自己,然后依次遍历配置每一个项目,最终入口都是config.因此我们就直接分析config。

@Override     public void configureHierarchy(ProjectInternal project) {         configure(project);         for (Project sub : project.getSubprojects()) {             configure((ProjectInternal) sub);         }     }  @Override  public void configure(ProjectInternal project) {         if (cancellationToken.isCancellationRequested()) {             throw new BuildCancelledException();         }         // Need to configure intermediate parent projects for configure-on-demand         ProjectInternal parentProject = project.getParent();         if (parentProject != null) {             configure(parentProject);         }         project.getOwner().ensureConfigured();     } 复制代码

最终调用eensureConfigured,通过层层导演,最终会调用ProjectConfigureAction的execute方法

//in class ConfigureActionsProjectEvaluator @Override     public void evaluate(ProjectInternal project, ProjectStateInternal state) {         for (ProjectConfigureAction configureAction : configureActions) {             configureAction.execute(project);         }     } 复制代码

ProjectConfigureAction的实现类有多个,我们看该类注释

/**  * Can be implemented by plugins to auto-configure each project.  *  * <p>Implementations are discovered using the JAR service locator mechanism (see {@link org.gradle.internal.service.ServiceLocator}).  * Each action is invoked for each project that is to be configured, before the project has been configured. Actions are executed  * in an arbitrary order.  */ public interface ProjectConfigureAction extends Action<ProjectInternal> { } 复制代码

其可被对应的插件实现,去配置每一个项目,这样结合我们在开发android项目都会使用插件,这样当执行到此阶段,即会自动配置,因此我们直接看对应的实现,即PluginsProjectConfigureActions

PluginsProjectConfigureActions自动配置每个Project

 @Override     public void execute(ProjectInternal project) {         for (Action<ProjectInternal> action : actions) {             action.execute(project);         }     } 复制代码

到这里配置阶段结束,具体的配置有具体的插件实现,其会在此阶段配置好自己。我们WrapperPluginAutoApplyAction为例,其最终会调用我们对应插件的apply方法。

public void execute(ProjectInternal project) {         project.getPluginManager().apply("org.gradle.wrapper");     } 复制代码

这里配置的是wrapper这个插件。我们查看给方法注释

/**     * Applies the plugin with the given ID. Does nothing if      * the plugin has already been applied.     * <p>     * Plugins in the {@code "org.gradle"} namespace can be applied      *directly via name.     * That is, the following two lines are equivalent…     * <pre>     * pluginManager.apply "org.gradle.java"     * pluginManager.apply "java"     * </pre>     *     * @param pluginId the ID of the plugin to apply     * @since 2.3     */     void apply(String pluginId); 复制代码

总结

该阶段主要会默认配置org.gradle下的Project,然后调用具体每个插件的实现,配置每个插件。

TaskGraph

接下来是task有向图的构建,其在上一阶段的基础上,配置每个task的依赖关系。

ScheduleTasks

分析任务图的构建我们需要回到流程图分析那里,其调用VintageBuildController.doBuildStage的发起点是在DefaultTreeWorkPrepare.这里其分成了多个阶段,即其首先调用doBuildStage达到_TaskSchedule_ �阶段,然后调用populateTaskGraph真正的构建任务图**。**我们看起代码

         // in the  DefaultTreeWorkPrepare     @Override     public void scheduleRequestedTasks() {         //该方法到达TaskSchedule         buildController.prepareToScheduleTasks();         //完成真正task有向图构建         includedBuildTaskGraph.prepareTaskGraph(() -> {         //处理初步任务有向图             buildController.scheduleRequestedTasks();         //填充任务图             includedBuildTaskGraph.populateTaskGraphs();         //结束构建,根据输入发起任务         buildController.finalizeWorkGraph(true);         });     } 复制代码

prepareTaskGraph

doBuildStages内部,在执行完配置后,进入下一个阶段,调用该方法,将其Stage转移到ScheduTasks,我们查看源码看起做了什么工作 其通过TaskGraphPrepares的prepareForTaskScheduling开启处理

private void prepareTaskGraph() {    controller.transitionIfNotPreviously(Stage.Configure, Stage.ScheduleTasks,     () -> taskGraphPreparer.prepareForTaskScheduling(gradle)); } 复制代码

TaskGraphPrepares有两个实现类,类似上面的处理也是逐级嵌套依次处理。其分别是:

  • DefaultTaskSchedulingPreparer

  • �ExcludedTaskFilteringProjectsPreparer

其中 DefaultTaskSchedulingPreparer存在delegate,因此其不是不最终的调用而是ExcludedTaskFilteringProjectsPreparer

    //DefaultTaskSchedulingPreparer     @Override     public void prepareForTaskScheduling(GradleInternal gradle) {         // Make root build substitutions available         if (gradle.isRootBuild()) {             buildStateRegistry.afterConfigureRootBuild();         }         delegate.prepareForTaskScheduling(gradle);     }    // ExcludedTaskFilteringProjectsPreparer     @Override     public void prepareForTaskScheduling(GradleInternal gradle) {         Set<String> excludedTaskNames = gradle.getStartParameter().getExcludedTaskNames();         if (!excludedTaskNames.isEmpty()) {             final Set<Spec<Task>> filters = new HashSet<Spec<Task>>();             for (String taskName : excludedTaskNames) {                 filters.add(taskSelector.getFilter(taskName));             }             gradle.getTaskGraph().useFilter(Specs.intersect(filters));         }     } 复制代码

查看代码我们知道,这里主要做了两部分工作

  1. DefaultTaskSchedulingPreparer通知项目配置完成

  2. 将不需要添加到依赖图的任务排除

prepareTaskGraph

IncludedBuildTaskGraph在VintageBuildController.doBuildStage到达ScheduleTask后,完成前期工作后开始构建任务图,其实现类为DefalutIncludedBuildTaskGraph

/** * Does the work to schedule tasks and prepare the task graphs for execution. */ void prepareTaskGraph(Runnable action){     withState(() -> {       expectInState(State.NotPrepared);       state = State.QueuingTasks;       buildOperationExecutor.run(new RunnableBuildOperation() {         @Override         public void run(BuildOperationContext context) {            action.run();            context.setResult(new CalculateTreeTaskGraphBuildOperationType.Result() {           });                 }           @Override           public BuildOperationDescriptor.Builder description() {             return BuildOperationDescriptor                 .displayName("Calculate build tree task graph")              .details(new CalculateTreeTaskGraphBuildOperationType.Details() {               });                 }             });             expectInState(State.Populated);             state = State.ReadyToRun;             return                      } 复制代码

该方法是通过CalculateTreeTaskGraphBuildOperationType告知我们做了什么,同时保存结果。其真正的工作是action.run,其实际调用的就是里面包裹的方法

/**  * Computing the task graph for the build tree based on the inputs   * and build configuration.  */ public final class CalculateTreeTaskGraphBuildOperationTyp     复制代码

includedBuildTaskGraph.prepareTaskGraph(() -> {             buildController.scheduleRequestedTasks();             includedBuildTaskGraph.populateTaskGraphs();             buildController.finalizeWorkGraph(true);         }) 复制代码

TaskExecution

其主要为task的执行配置Gradle对象,其是通过TaskExecutionPreparer的prepareForTaskExecution发起

/**  * Responsible for preparing `Gradle` instances for task execution. The result is passed to a {@link org.gradle.execution.BuildWorkExecutor} for execution. Prior to preparing for task execution, the `Gradle` instance has its projects configured by a {@link org.gradle.configuration.ProjectsPreparer}.  *  * <p>This includes resolving the entry tasks and calculating the task graph.</p>  */ public interface TaskExecutionPreparer {     void prepareForTaskExecution(GradleInternal gradle); } 复制代码

�查看类注释,其主要解决Task入口,和任务图计算,其实现类为DefaultTaskExecutionPreparer,

@Override     public void prepareForTaskExecution(GradleInternal gradle) {         buildConfigurationActionExecuter.select(gradle);         if (buildModelParameters.isConfigureOnDemand() && gradle.isRootBuild()) {             new ProjectsEvaluatedNotifier(buildOperationExecutor).notify(gradle);         }     } 复制代码

�其核心在第一个调用,其会对任务进行选择. 其通过buildConfigurationActionExecuter的seletc发起

 @Override     public void select(final GradleInternal gradle) {         // We know that we're running single-threaded here, so we can use coarse grained locks         projectStateRegistry.withMutableStateOfAllProjects(() -> {             configure(taskSelectors, gradle, 0);         });     } 复制代码

其中configure内部为遍历taskSelectors,依次取出每一个taskSelector,即BuildConfigurationAction �然后调用其config去筛选计算任务。

rivate void configure(final List<? extends BuildConfigurationAction> processingConfigurationActions, final GradleInternal gradle, final int index) {         if (index >= processingConfigurationActions.size()) {             return;         }         processingConfigurationActions.get(index).configure(new BuildExecutionContext() {             @Override             public GradleInternal getGradle() {                 return gradle;             }             @Override             public void proceed() {                 configure(processingConfigurationActions, gradle, index + 1);             }         });     } 复制代码

BuildConfigurationAction

其默认有两个实现类,因此遍历即分别调用这两个类

  • DefaultTasksBuildExecutionAction

  • TaskNameResolvingBuildConfigurationAction

  1. TaskNameResolvingBuildConfigurationAction

其根据平常去构建taskGraph

 @Override     public void configure(BuildExecutionContext context) {         GradleInternal gradle = context.getGradle();         TaskExecutionGraphInternal taskGraph = gradle.getTaskGraph();         List<TaskExecutionRequest> taskParameters = gradle.getStartParameter().getTaskRequests();         for (TaskExecutionRequest taskParameter : taskParameters) {             List<TaskSelection> taskSelections = commandLineTaskParser.parseTasks(taskParameter);             for (TaskSelection taskSelection : taskSelections) {                 LOGGER.info("Selected primary task '{}' from project {}", taskSelection.getTaskName(), taskSelection.getProjectPath());                 //添加到taskGraph                 taskGraph.addEntryTasks(taskSelection.getTasks());             }         }         context.proceed();     } 复制代码

  1. DefaultTasksBuildExecutionAction

�其是处理project默认的task,如果没有会为其添加helpTask

public void configure(BuildExecutionContext context) {         StartParameter startParameter = context.getGradle().getStartParameter();         for (TaskExecutionRequest request : startParameter.getTaskRequests()) {             if (!request.getArgs().isEmpty()) {                 context.proceed();                 return;             }         }         // 获取Project默认的Tasks         ProjectInternal project = context.getGradle().getDefaultProject();         //so that we don't miss out default tasks         projectConfigurer.configure(project);         //处理默认的task         List<String> defaultTasks = project.getDefaultTasks();         if (defaultTasks.size() == 0) {             defaultTasks = new ArrayList<>();             for (BuiltInCommand command : builtInCommands) {                 defaultTasks.addAll(command.asDefaultTask());             }             LOGGER.info("No tasks specified. Using default task {}", GUtil.toString(defaultTasks));         } else {             LOGGER.info("No tasks specified. Using project default tasks {}", GUtil.toString(defaultTasks));         }         //将处理后的tasks,设置到参数里,交由我们上面分析的TaskNameResolvingBuildConfigurationAction         //处理         startParameter.setTaskNames(defaultTasks);         context.proceed();     } 复制代码

到这里,通过doBuildStage中的prepareForTaskExecution,我们将处理后的任务添加到了taskGraph中。

populateTaskGraphs

该方法完成任务图的填充。

/**      * Finish populating task graphs, once all entry point tasks have been scheduled.      */     void populateTaskGraphs();  @Override     public void populateTaskGraphs() {         withState(() -> {             assertCanQueueTask();             includedBuilds.populateTaskGraphs();             state = State.Populated;             return null;         });     } 复制代码

Controller填充任务图

填充任务图具体有对应的IncludeBuildControllers完成

@Override     public void populateTaskGraphs() {         boolean tasksDiscovered = true;         while (tasksDiscovered) {             tasksDiscovered = false;             for (IncludedBuildController buildController : ImmutableList.copyOf(buildControllers.values())) {                 if (buildController.populateTaskGraph()) {                     tasksDiscovered = true;                 }             }         }         for (IncludedBuildController buildController : buildControllers.values()) {             buildController.prepareForExecution();         }     } 复制代码

到这里就完成了任务图的构建,同时为下一步任务执行做好准备,触发时间开始执行任务

finalizeWorkGraph

�其会调用taskGraph的polulate,如果一切就绪

 @Override     public void finalizeWorkGraph(boolean workScheduled) {         if (workScheduled) {             TaskExecutionGraphInternal taskGraph = gradle.getTaskGraph();             taskGraph.populate();         }         finalizeGradleServices(gradle);     } 复制代码

我们查看该方法对应的注释

   /**      * Does the work to populate the task graph based on tasks that have been added. Fires events and no further tasks should be added.      */     void populate(); 复制代码

后续具体执行这里就不分析了。

总结

经过上面的整个分析,我们就清楚的知道了,当我们在AndroidStudio中敲下命令后,其如何去检测我们gradle的版本,并进行下载。同时我们项目中的setting.gradle的作用,最后就是任务如何添加,依赖关系如何构建。其中有的地方逻辑比较复杂,这里没有去深入分析,重点是掌握其整个流程。后续有需要,我们就可深入去分析研究它。


作者:莫名Font
链接:https://juejin.cn/post/7032885152132890637

文章分类
代码人生
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐