更改依赖项时,Gradle 通过不重新编译那些无法被访问的依赖项 API 模块来加快编译速度。此时可以利用 Gradle 的新依赖项配置(implementation、api、compileOnly 和 runtimeOnly)限制哪些依赖项会将其 API 泄露给其他模块。

2)、借助每个类的 dex 处理,可加快增量编译速度。

每个类现在都会编译成单独的 DEX 文件,并且只会对修改过的类重新进行 dex 处理

3)、启用 Gradle 编译缓存优化某些任务来使用缓存的输出

启用 Gradle 编译缓存能够优化某些任务来使用缓存的输出,从而加快编译速度。

4)、AAPT2 默认已启用并改进了增量资源处理

如果在使用 AAPT2 时遇到了问题,我们可以停用 AAPT2,在 gradle.properties 文件中设置如下代码:

android.enableAapt2=false

然后,通过在命令行中运行 ./gradlew --stop 来重启 Gradle 守护进程

7、Android Gradle Plugin V2.3.0(2017 年 2 月)

1)、增加编译缓存

存储编译项目时 Android 插件生成的特定输出。使用缓存时,编译插件的速度会明显加快,因为编译系统在进行后续编译时可以直接重用这些缓存文件,而不必重新创建。此外,我们也可以 使用 cleanBuildCache Task 去清除编译缓存

更老版本的的更新细节请查阅 gradle-plugin

三、Gradle 构建核心流程解析

当我们输入 ./gradlew/gradle … 命令之后,一个 Gradle 构建就开始了。它包含如下 三个步骤

  • 1)、首先,初始化 Gradle 构建框架自身
  • 2)、然后,把命令行参数包装好送给 DefaultGradleLauncher
  • 3)、最后,触发 DefaultGradleLauncher 中 Gradle 构建的生命周期,并开始执行标准的构建流程

在开始深入源码之前,我们可以先自顶向下了解下 Gradle 构建的核心流程图,以便对 Gradle 的构建流程建立一个整体的感知。

当我们执行一个 gralde 命令时,便会调用 gradle/wrapper/gradle-wrapper.jar 里面 org.gradle.wrapper.GradleWrapperMain 类的 main 方法,它就是 gradle 的一个入口方法。该方法的核心源码如下所示:

public static void main(String[] args) throws Exception {

// 1、索引到 gradle-wrapper.properties 文件中配置的 gradle zip 地址,并由此包装成一个 WrapperExecutor 实例。
WrapperExecutor wrapperExecutor = WrapperExecutor.forWrapperPropertiesFile(propertiesFile);
// 2、使用 wrapperExecutor 实例的 execute 方法执行 gradle 命令。
wrapperExecutor.execute(args, new Install(logger, new Download(logger, “gradlew”, “0”), new PathAssembler(gradleUserHome)), new BootstrapMainStarter());
}

然后,我们继续看看 wrapperExecutor 的 execute 方法,源码如下所示:

public void execute(String[] args, Install install, BootstrapMainStarter bootstrapMainStarter) throws Exception {
// 1、下载 gradle wrapper 需要的依赖与源码。
File gradleHome = install.createDist(this.config);
// 2、从这里开始执行 gradle 的构建流程。
bootstrapMainStarter.start(args, gradleHome);
}

首先,在注释1处,会下载 gradle wrapper 需要的依赖与源码。接着,在注释2处,便会调用 bootstrapMainStarter 的 start 方法从这里开始执行 gradle 的构建流程。其内部最终会依次调用 DefaultGradleLauncher 的 getLoadedSettings、getConfiguredBuild、executeTasks 与 finishBuild 方法,而它们对应的状态都定义在 DefaultGradleLauncher 中的 Stage 枚举类中,如下所示:

private static enum Stage {
LoadSettings,
Configure,
TaskGraph,
RunTasks {
String getDisplayName() {
return “Build”;
}
},
Finished;

private Stage() {
}

String getDisplayName() {
return this.name();
}
}

下面,我们就对这五个流程来进行详细地分析。

1、LoadSettings

当调用 getLoadedSettings 方法时便开始了加载 Setting.gradle 的流程。其源码如下所示:

public SettingsInternal getLoadedSettings() {
this.doBuildStages(DefaultGradleLauncher.Stage.LoadSettings);
return this.gradle.getSettings();
}

这里又继续调用了 doBuildStages 方法进行处理,内部实现如下所示:

private void doBuildStages(DefaultGradleLauncher.Stage upTo) {
Preconditions.checkArgument(upTo != DefaultGradleLauncher.Stage.Finished, “Stage.Finished is not supported by doBuildStages.”);

try {
// 当 Stage 是 RunTask 的时候执行。
if (upTo == DefaultGradleLauncher.Stage.RunTasks && this.instantExecution.canExecuteInstantaneously()) {
this.doInstantExecution();
} else {
// 当 Stage 不是 RunTask 的时候执行。 this.doClassicBuildStages(upTo);
}
} catch (Throwable var3) {
this.finishBuild(upTo.getDisplayName(), var3);
}

}

继续调用 doClassicBuildStages 方法,源码如下所示:

private void doClassicBuildStages(DefaultGradleLauncher.Stage upTo) {
// 1、当 Stage 为 LoadSettings 时执行 prepareSettings 方法去配置并生成 Setting 实例。
this.prepareSettings();
if (upTo != DefaultGradleLauncher.Stage.LoadSettings) {
// 2、当 Stage 为 Configure 时执行 prepareProjects 方法去配置工程。
this.prepareProjects();
if (upTo != DefaultGradleLauncher.Stage.Configure) {
// 3、当 Stage 为 TaskGraph 时执行 prepareTaskExecution 方法去构建 TaskGraph。
this.prepareTaskExecution();
if (upTo != DefaultGradleLauncher.Stage.TaskGraph) {

// 4、当 Stage 为 RunTasks 时执行 saveTaskGraph 方法 与 runWork 方法保存 TaskGraph 并执行相应的 Tasks。 this.instantExecution.saveTaskGraph();
this.runWork();
}
}
}
}

可以看到,doClassicBuildStages 方法是个很重要的方法,它对所有的 Stage 任务进行了分发,这里小结一下:

  • 1)、当 Stage 为 LoadSettings 时执行 prepareSettings 方法去配置并生成 Setting 实例
  • 2)、当 Stage 为 Configure 时执行 prepareProjects 方法去配置工程
  • 3)、当 Stage 为 TaskGraph 时执行 prepareTaskExecution 方法去构建 TaskGraph
  • 4)、当 Stage 为 RunTasks 时执行 saveTaskGraph 方法 与 runWork 方法保存 TaskGraph 并执行相应的 Tasks

然后,我们接着继续看看 prepareSettings 方法,其源码如下所示:

private void prepareSettings() {
if (this.stage == null) {
// 1、回调 BuildListener.buildStarted() 回调接口。
this.buildListener.buildStarted(this.gradle);
// 2、调用 settingPreparer 接口的实现类 DefaultSettingsPreparer 的 prepareSettings 方法。
this.settingsPreparer.prepareSettings(this.gradle);
this.stage = DefaultGradleLauncher.Stage.LoadSettings;
}
}

prepareSettings 方法做了两件事:

  • 1)、回调 BuildListener.buildStarted 接口
  • 2)、调用 settingPreparer 接口的实现类 DefaultSettingsPreparer 的 prepareSettings 方法

我们继续看到 DefaultSettingsPreparer 的 prepareSettings 方法,如下所示:

public void prepareSettings(GradleInternal gradle) {
// 1、执行 init.gradle,它会在每个项目 build 之前被调用,用于做一些初始化的操作。
this.initScriptHandler.executeScripts(gradle);
SettingsLoader settingsLoader = gradle.getParent() != null ? this.settingsLoaderFactory.forNestedBuild() : this.settingsLoaderFactory.forTopLevelBuild();
// 2、调用 SettingLoader 接口的实现类 DefaultSettingsLoader 的 findAndLoadSettings 找到 Settings.gradle 文件的位置。
settingsLoader.findAndLoadSettings(gradle);
}

prepareSettings 方法中做了两项处理:

  • 1)、执行 init.gradle,它会在每个项目 build 之前被调用,用于做一些初始化的操作
  • 2)、调用 SettingLoader 接口的实现类 DefaultSettingsLoader 的 findAndLoadSettings 找到 Settings.gradle 文件的位置

DefaultSettingLoader 的 findAndLoadSettings 方法关联的实现代码非常多,限于篇幅,我这里直接点出 findAndLoadSettings 方法中的主要处理流程

  • 1)、首先,查找 settings.gradle 位置
  • 2)、然后,编译 buildSrc(Android 默认的 Plugin 目录)文件夹下的内容
  • 3)、接着,解析 gradle.properites 文件:这里会读取 gradle.properties 文件里的配置信息与命令行传入的配置属性并存储
  • 4)、然后,解析 settings.gradle 文件:这里最后会调用 BuildOperationScriptPlugin.apply 去执行 settings.gradle 文件
  • 5)、最后,根据 Settings.gradle 文件中获得的信息去创建 project 以及 subproject 实例

2、Configure

当执行完 LoadSetting 阶段之后,就会执行 Configure 阶段,而配置阶段所作的事情就是 把 gradle 脚本编译成 class 文件并执行。由前可知,此时会执行 prepareProjects 方法,如下所示:

private void prepareProjects() {
if (this.stage == DefaultGradleLauncher.Stage.LoadSettings) {
// 1、调用 ProjectsPreparer 接口的实现类 DefaultProjectsPreparer 的 prepareProjects 方法。
this.projectsPreparer.prepareProjects(this.gradle);
this.stage = DefaultGradleLauncher.Stage.Configure;
}
}

这里会继续调用 ProjectsPreparer 接口的实现类 DefaultProjectsPreparer 的 prepareProjects 方法。其源码如下所示:

public void prepareProjects(GradleInternal gradle) {

// 1、如果在 gradle.properties 文件中指定了参数 configure-on-demand,则只会配置主项目以及执行 task 所需要的项目。
if (gradle.getStartParameter().isConfigureOnDemand()) {
this.projectConfigurer.configure(gradle.getRootProject());
} else {
// 2、如果没有指定在 gradle.properties 文件中指定参数 configure-on-demand,则会调用 ProjectConfigurer 接口的实现类 TaskPathProjectEvaluator 的 configureHierarchy 方法去配置所有项目。
this.projectConfigurer.configureHierarchy(gradle.getRootProject());
(new ProjectsEvaluatedNotifier(this.buildOperationExecutor)).notify(gradle);
}

this.modelConfigurationListener.onConfigure(gradle);
}

在注释1处,如果在 gradle.properties 文件中指定了参数 configure-on-demand,则只会配置主项目以及执行 task 所需要的项目。我们这里只看默认没有指定的情况。否则,在注释2处,则会调用 ProjectConfigurer 接口的实现类 TaskPathProjectEvaluator 的 configureHierarchy 方法去配置所有项目。

我们接着继续看到 configureHierarchy 方法,如下所示:

public void configureHierarchy(ProjectInternal project) {
this.configure(project);
Iterator var2 = project.getSubprojects().iterator();

while(var2.hasNext()) {
Project sub = (Project)var2.next();
this.configure((ProjectInternal)sub);
}
}

可以看到在 configureHierarchy 方法中使用了 Iterator 遍历并配置了所有 Project。而 configure 方法最终会调用到 EvaluateProject 类的 run 方法,如下所示:

public void run(final BuildOperationContext context) {
this.project.getMutationState().withMutableState(new Runnable() {
public void run() {
try {

EvaluateProject.this.state.toBeforeEvaluate();

// 1、 回调 ProjectEvaluationListener 的 beforeEvaluate 接口。
LifecycleProjectEvaluator.this.buildOperationExecutor.run(new LifecycleProjectEvaluator.NotifyBeforeEvaluate(EvaluateProject.this.project, EvaluateProject.this.state));

if (!EvaluateProject.this.state.hasFailure()) {
EvaluateProject.this.state.toEvaluate();

try {
// 2、在 evaluate 方法中会设置默认的 init、wrapper task 和 默认插件,然后便会编译、执行 build.gradle 脚本
LifecycleProjectEvaluator.this.delegate.evaluate(EvaluateProject.this.project, EvaluateProject.this.state);
} catch (Exception var10) {
LifecycleProjectEvaluator.addConfigurationFailure(EvaluateProject.this.project, EvaluateProject.this.state, var10, context);
} finally {
EvaluateProject.this.state.toAfterEvaluate();
// 3、回调 ProjectEvaluationListener.afterEvaluate 接口。
LifecycleProjectEvaluator.this.buildOperationExecutor.run(new LifecycleProjectEvaluator.NotifyAfterEvaluate(EvaluateProject.this.project, EvaluateProject.this.state));
}
}

if (EvaluateProject.this.state.hasFailure()) {
EvaluateProject.this.state.rethrowFailure();
} else {
context.setResult(ConfigureProjectBuildOperationType.RESULT);
}
} finally {
EvaluateProject.this.state.configured();
}

}
});
}

在 EvaluateProject 的 run 方法中有如下 三个重要的处理

  • 1)、回调 ProjectEvaluationListener 的 beforeEvaluate 接口
  • 2)、在 evaluate 方法中会设置默认的 init、wrapper task 和 默认插件,然后便会编译并执行 build.gradle 脚本
  • 3)、回调 ProjectEvaluationListener.afterEvaluate 接口

3、TaskGraph

执行完 初始化阶段 与 配置阶段 之后,就会 调用到 DefaultGradleLauncher 的 prepareTaskExecution 方法去创建一个由 Tasks 组成的一个有向无环图。该方法如下所示:

private void prepareTaskExecution() {
if (this.stage == DefaultGradleLauncher.Stage.Configure) {
// 1、调用 TaskExecutionPreparer 接口的实现类 BuildOperatingFiringTaskExecutionPreparer 的 prepareForTaskExecution 方法。
this.taskExecutionPreparer.prepareForTaskExecution(this.gradle);
this.stage = DefaultGradleLauncher.Stage.TaskGraph;
}
}

这里继续调用了 TaskExecutionPreparer 接口的实现类 BuildOperatingFiringTaskExecutionPreparer 的 prepareForTaskExecution 方法,如下所示:

public void prepareForTaskExecution(GradleInternal gradle) {
this.buildOperationExecutor.run(new BuildOperatingFiringTaskExecutionPreparer.CalculateTaskGraph(gradle));
}

可以看到,这里使用 buildOperationExecutor 实例执行了 CalculateTaskGraph 这个构建操作,我们看到它的 run 方法,如下所示:

public void run(BuildOperationContext buildOperationContext) {
// 1、填充任务图
final TaskExecutionGraphInternal taskGraph = this.populateTaskGraph();
buildOperationContext.setResult(new Result() {
getRequestedTaskPaths() {
return this.toTaskPaths(taskGraph.getRequestedTasks());
}

public List getExcludedTaskPaths() {
return this.toTaskPaths(taskGraph.getFilteredTasks());
}

private List toTaskPaths(Set tasks) {
return ImmutableSortedSet.copyOf(Collections2.transform(tasks, new Function<Task, String>() {
public String apply(Task task) {
return task.getPath();
}
})).asList();
}
});
}

在注释1处,直接调用了 populateTaskGraph 填充了 Tasks 有向无环图。源码如下所示:

TaskExecutionGraphInternal populateTaskGraph() {
// 1、这里又调用了 TaskExecutionPreparer 接口的另一个实现类 DefaultTaskExecutionPreparer 的 prepareForTaskExecution 方法。
BuildOperatingFiringTaskExecutionPreparer.this.delegate.prepareForTaskExecution(this.gradle);
return this.gradle.getTaskGraph();
}

可以看到,在注释1处,又调用了 TaskExecutionPreparer 接口的另一个实现类 DefaultTaskExecutionPreparer 的 prepareForTaskExecution 方法。该方法如下所示:

public void prepareForTaskExecution(GradleInternal gradle) {
// 1
this.buildConfigurationActionExecuter.select(gradle);
TaskExecutionGraphInternal taskGraph = gradle.getTaskGraph();
// 2、根据 Tasks 与 Tasks 间的依赖信息填充 taskGraph 实例。
taskGraph.populate();
this.includedBuildControllers.populateTaskGraphs();
if (gradle.getStartParameter().isConfigureOnDemand()) {
(new ProjectsEvaluatedNotifier(this.buildOperationExecutor)).notify(gradle);
}
}

在注释1处,调用了 buildConfigurationActionExecuter 接口的 select 方法,这里采用了 策略 + 接口隔离 设计模式,后续会依次调用 ExcludedTaskFilteringBuildConfigurationAction 的 configure 方法、 DefaultTasksBuildExecutionAction 的 configure 方法、TaskNameResolvingBuildConfigurationAction 的 configure 方法

下面,我们依次来分析下其中的处理。

1)、ExcludedTaskFilteringBuildConfigurationAction#configure:处理需要排除的 task

public void configure(BuildExecutionContext context) {
// 1、获取被排除的 Tasks 名称,并依次把它们放入 filters 中。
GradleInternal gradle = context.getGradle();
Set excludedTaskNames = gradle.getStartParameter().getExcludedTaskNames();
if (!excludedTaskNames.isEmpty()) {
Set<Spec> filters = new HashSet();
Iterator var5 = excludedTaskNames.iterator();

while(var5.hasNext()) {
String taskName = (String)var5.next();
filters.add(this.taskSelector.getFilter(taskName));
}

// 2、给 TaskGraph 实例添加要 filter 的 Tasks
gradle.getTaskGraph().useFilter(Specs.intersect(filters));
}

context.proceed();
}

在注释1处,先获取了被排除的 Tasks 名称,并依次把它们放入 filters 中,接着在注释2处给 TaskGraph 实例添加了要 filter 的 Tasks。

可以看到,这里给 TaskGraph 设置了 filter 去处理需要排除的 task,以便在后面计算依赖的时候排除相应的 task

2)、DefaultTasksBuildExecutionAction#configure:添加默认的 task

public void configure(BuildExecutionContext context) {
StartParameter startParameter = context.getGradle().getStartParameter();
Iterator var3 = startParameter.getTaskRequests().iterator();

TaskExecutionRequest request;
// 1、如果指定了要执行的 Task,则什么也不做。
do {
if (!var3.hasNext()) {
ProjectInternal project = context.getGradle().getDefaultProject();
this.projectConfigurer.configure(project);
List defaultTasks = project.getDefaultTasks();
// 2、如果没有指定 DefaultTasks,则输出 gradle help 信息。
if (defaultTasks.size() == 0) {
defaultTasks = Collections.singletonList(“help”);
LOGGER.info(“No tasks specified. Using default task {}”, GUtil.toString(defaultTasks));
} else {
LOGGER.info(“No tasks specified. Using project default tasks {}”, GUtil.toString(defaultTasks));
}

// 3、否则,添加默认的 Task。
startParameter.setTaskNames(defaultTasks);
context.proceed();
return;
}

request = (TaskExecutionRequest)var3.next();
} while(request.getArgs().isEmpty());

context.proceed();
}

可以看到,DefaultTasksBuildExecutionAction 类的 configure 方法的处理分为如下三步:

  • 1、如果指定了要执行的 Task,则什么也不做
  • 2、如果没有指定 defaultTasks,则输出 gradle help 信息
  • 3、否则,添加默认的 defaultTasks

3)、TaskNameResolvingBuildConfigurationAction#configure:计算 task 依赖图

public void configure(BuildExecutionContext context) {
GradleInternal gradle = context.getGradle();
TaskExecutionGraphInternal taskGraph = gradle.getTaskGraph();
List taskParameters = gradle.getStartParameter().getTaskRequests();
Iterator var5 = taskParameters.iterator();

while(var5.hasNext()) {
TaskExecutionRequest taskParameter = (TaskExecutionRequest)var5.next();
// 1、解析 Tasks。
List taskSelections = this.commandLineTaskParser.parseTasks(taskParameter);
Iterator var8 = taskSelections.iterator();

// 2、遍历并添加所有已选择的 Tasks 至 taskGraph 实例之中。
while(var8.hasNext()) {
TaskSelection taskSelection = (TaskSelection)var8.next();
LOGGER.info(“Selected primary task ‘{}’ from project {}”, taskSelection.getTaskName(), taskSelection.getProjectPath());
taskGraph.addEntryTasks(taskSelection.getTasks());
}
}

context.proceed();
}

这里主要做了 两个处理

  • 1)、解析 Tasks分析命令行中的 Task 的参数前面是否指定了 Project,例如 ‘:project:assembleRelease’,如果没有指定则选中 Project 下所有符合该 taskName 的 Task
  • 2)、遍历并添加所有已选择的 Tasks 至 taskGraph 实例之中在内部会处理 dependson finalizedby mustrunafter shouldrunafter 等 Tasks 间的依赖关系,并会把信息保存在 TaskInfo 之中

4)、填充 task 依赖图

最后,我们再回到 DefaultTaskExecutionPreparer 的 prepareForTaskExecution 方法,在注释2处,我们就可以 调用 taskGraph 的 populate 方法去根据这些 Tasks 与 Tasks 之间的依赖信息去填充 taskGraph 实例了

4、RunTasks

填充完 taskGraph 之后,我们就可以开始来执行这些 Tasks 了,我们看到 DefaultGradleLauncher 实例的 executeTasks 方法,如下所示:

public GradleInternal executeTasks() {
this.doBuildStages(DefaultGradleLauncher.Stage.RunTasks);
return this.gradle;
}

在 doBuildStages 方法中又会调用 doClassicBuildStages 方法,源码如下所示:

private void doClassicBuildStages(DefaultGradleLauncher.Stage upTo) {
this.prepareSettings();
if (upTo != DefaultGradleLauncher.Stage.LoadSettings) {
this.prepareProjects();
if (upTo != DefaultGradleLauncher.Stage.Configure) {
this.prepareTaskExecution();
if (upTo != DefaultGradleLauncher.Stage.TaskGraph) {
this.instantExecution.saveTaskGraph();
// 1
this.runWork();
}
}
}
}

在注释1处,继续调用了 runWork 方法,如下所示:

private void runWork() {
if (this.stage != DefaultGradleLauncher.Stage.TaskGraph) {
throw new IllegalStateException("Cannot execute tasks: current stage = " + this.stage);
} else {
List taskFailures = new ArrayList();
// 1
this.buildExecuter.execute(this.gradle, taskFailures);
if (!taskFailures.isEmpty()) {
throw new MultipleBuildFailures(taskFailures);
} else {
this.stage = DefaultGradleLauncher.Stage.RunTasks;
}
}
}

这里又继续 调用了 buildExecuter 接口的实现类 DefaultBuildWorkExecutor 的 execute 方法,其实现如下所示:

public void execute(GradleInternal gradle, Collection<? super Throwable> failures) {
this.execute(gradle, 0, failures);
}

private void execute(final GradleInternal gradle, final int index, final Collection<? super Throwable> taskFailures) {
if (index < this.executionActions.size()) {
// 1
((BuildExecutionAction)this.executionActions.get(index)).execute(new BuildExecutionContext() {
public GradleInternal getGradle() {
return gradle;
}

public void proceed() {
// 2、执行完 executionActions 列表中的第一项后,便开始执行下一项。
DefaultBuildWorkExecutor.this.execute(gradle, index + 1, taskFailures);
}
}, taskFailures);
}
}

1)、执行 DryRunBuildExecutionAction:处理 DryRun

可以看到,这里又调用了 BuildExecutionAction 接口的实现类 DryRunBuildExecutionAction 的 execute 方法,如下所示:

public void execute(BuildExecutionContext context, Collection<? super Throwable> taskFailures) {
GradleInternal gradle = context.getGradle();
// 1、如果命令行里包含 --dry-run 参数,则会跳过该 Task 的执行,并输出 Task 的名称与执行的先后关系。
if (gradle.getStartParameter().isDryRun()) {
Iterator var4 = gradle.getTaskGraph().getAllTasks().iterator();

while(var4.hasNext()) {
Task task = (Task)var4.next();
this.textOutputFactory.create(DryRunBuildExecutionAction.class).append(((TaskInternal)task).getIdentityPath().getPath()).append(" ").style(Style.ProgressStatus).append(“SKIPPED”).println();
}
} else {
context.proceed();
}
}

在注释1处,如果命令行里包含了 --dry-run 参数,则会跳过该 Task 的执行,并输出 Task 的名称与执行的先后关系

2)、执行:SelectedTaskExecutionAction:使用线程执行被选择的 Tasks

执行完 DryRunBuildExecutionAction 后,我们再回到 DefaultBuildWorkExecutor 类的 execute 方法,在注释2处,会执行 executionActions 列表中的下一项,即第二项:SelectedTaskExecutionAction,我们看看它的 execute 方法,如下所示:

public void execute(BuildExecutionContext context, Collection<? super Throwable> taskFailures) {

taskGraph.addTaskExecutionGraphListener(new SelectedTaskExecutionAction.BindAllReferencesOfProjectsToExecuteListener());

// 1、
taskGraph.execute(taskFailures);
}

可以看到,这里直接调用了 TaskExecutionGraphInternal 接口的实现类 DefaultTaskExecutionGraph 的 execute 方法去执行 Tasks,其关键源码如下所示:

public void execute(Collection<? super Throwable> failures) {
ProjectExecutionServiceRegistry projectExecutionServices = new ProjectExecutionServiceRegistry();

try {
// 使用线程池执行 Task
this.executeWithServices(projectExecutionServices, failures);
} finally {
projectExecutionServices.close();
}
}

这里又继续调用了 DefaultTaskExecutionGraph 的 executeWithServices 方法使用线程池并行执行 Task,其核心源码如下所示:

private void executeWithServices(ProjectExecutionServiceRegistry projectExecutionServices, Collection<? super Throwable> failures) {

this.ensurePopulated();

try {
// 1
this.planExecutor.process(this.executionPlan, failures, new DefaultTaskExecutionGraph.BuildOperationAwareExecutionAction(this.buildOperationExecutor.getCurrentOperation(), new DefaultTaskExecutionGraph.InvokeNodeExecutorsAction(this.nodeExecutors, projectExecutionServices)));
LOGGER.debug("Timing: Executing the DAG took " + clock.getElapsed());
} finally {

}
}

最终,这里是 调用了 PlanExecutor 接口的实现类 DefaultPlanExecutor 的 process 方法,如下所示:

public void process(ExecutionPlan executionPlan, Collection<? super Throwable> failures, Action nodeExecutor) {
ManagedExecutor executor = this.executorFactory.create(“Execution worker for '” + executionPlan.getDisplayName() + “'”);

try {
WorkerLease parentWorkerLease = this.workerLeaseService.getCurrentWorkerLease();
// 1、开始使用线程池异步执行 tasks
this.startAdditionalWorkers(executionPlan, nodeExecutor, executor, parentWorkerLease);
(new DefaultPlanExecutor.ExecutorWorker(executionPlan, nodeExecutor, parentWorkerLease, this.cancellationToken, this.coordinationService)).run();
this.awaitCompletion(executionPlan, failures);
} finally {
executor.stop();
}
}

在注释1处,使用了线程池去异步执行 tasks,如下所示:

private void startAdditionalWorkers(ExecutionPlan executionPlan, Action<? super Node> nodeExecutor, Executor executor, WorkerLease parentWorkerLease) {
LOGGER.debug(“Using {} parallel executor threads”, this.executorCount);

for(int i = 1; i < this.executorCount; ++i) {
executor.execute(new DefaultPlanExecutor.ExecutorWorker(executionPlan, nodeExecutor, parentWorkerLease, this.cancellationToken, this.coordinationService));
}
}

需要了解的是,用于执行 Task 的线程默认是 8 个线程。这里使用线程池执行了 DefaultPlanExecutor 的 ExecutorWorker,在它的 run 方法中最终会调用到 DefaultBuildOperationExecutor 的 run 方法去执行 Task。但在 Task 执行前还需要做一些预处理

3)、Task 执行前的一些预处理

在 DefaultBuildOperationExecutor 的 run 方法中只做了两件事,这里我们只需大致了解下即可,如下所示:

  • 1、首先,回调 TaskExecutionListener#beforeExecute

  • 2、然后,链式执行一系列对 Task 的通用处理,其具体的处理如下所示:

  • 1)、CatchExceptionTaskExecuter#execute增加 try catch,避免执行过程中发生异常

  • 2)、ExecuteAtMostOnceTaskExecuter#execute判断 task 是否执行过

  • 3)、SkipOnlyIfTaskExecuter#execute判断 task 的 onlyif 条件是否满足执行

  • 4)、SkipTaskWithNoActionsExecuter#execute跳过没有 action 的 task,如果没有 action 说明 task 不需要执行

  • 5)、ResolveTaskArtifactStateTaskExecuter#execute设置 artifact 的状态

  • 6)、SkipEmptySourceFilesTaskExecuter#execut跳过设置了 source file 且 source file 为空的 task,如果 source file 为空则说明 task 没有需要处理的资源

  • 7)、ValidatingTaskExecuter#execute确认 task 是否可以执行

  • 8)、ResolveTaskOutputCachingStateExecuter#execute处理 task 输出缓存

  • 9)、SkipUpToDateTaskExecuter#execute跳过 update-to-date 的 task

  • 10)、ExecuteActionsTaskExecuter#execute用来真正执行 Task 的 executer

可以看到,在真正执行 Task 前需要经历一些通用的 task 预处理,最后才会调用 ExecuteActionsTaskExecuter 的 execute 方法去真正执行 Task

4)、真正执行 Task

public TaskExecuterResult execute(final TaskInternal task, final TaskStateInternal state, final TaskExecutionContext context) {
final ExecuteActionsTaskExecuter.TaskExecution work = new ExecuteActionsTaskExecuter.TaskExecution(task, context, this.executionHistoryStore, this.fingerprinterRegistry, this.classLoaderHierarchyHasher);
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后

我这里整理了一份完整的学习思维以及Android开发知识大全PDF。

当然实践出真知,即使有了学习线路也要注重实践,学习过的内容只有结合实操才算是真正的掌握。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

13678439099)]

[外链图片转存中…(img-mSOIc2aX-1713678439100)]

[外链图片转存中…(img-9FHVAp8l-1713678439101)]

[外链图片转存中…(img-hMazEUmE-1713678439102)]

[外链图片转存中…(img-66o5OUHd-1713678439104)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后

我这里整理了一份完整的学习思维以及Android开发知识大全PDF。

[外链图片转存中…(img-1t55poSH-1713678439105)]

当然实践出真知,即使有了学习线路也要注重实践,学习过的内容只有结合实操才算是真正的掌握。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

Logo

一起探索未来云端世界的核心,云原生技术专区带您领略创新、高效和可扩展的云计算解决方案,引领您在数字化时代的成功之路。

更多推荐