Gradle 源碼分析(五)

1. 寫在前面

Gradle源碼分析(四)一文中,我們分析了Gradle構(gòu)建流程的 TaskGraph 階段鳍刷,這里將分析 RunTasks 階段(gradle 源碼版本為 5.6.4)。

2. RunTasks

2.1 整體實(shí)現(xiàn)

這里我整理了 RunTasks 階段的一些主要操作畏邢,并繪制了調(diào)用鏈的時(shí)序圖。如果對(duì)源碼不感興趣的同學(xué)只需要看這一部分的內(nèi)容即可兽间。

2.1.1 時(shí)序圖

RunTasks時(shí)序圖.png

2.1.2 主要操作

RunTasks 階段 Gradle 主要做了下面這些事情预烙。

  1. 處理 --dry-run;
  2. 回調(diào)傳給 whenReady() 的閉包谴仙;
  3. 創(chuàng)建線程和 ExecutorWorker迂求;
  4. 執(zhí)行 task 前的預(yù)處理碾盐;
  5. 調(diào)用 TaskActionListenerbeforeAction()晃跺,遍歷 TaskAction ,并調(diào)用其 execute()毫玖,調(diào)用 TaskActionListenerafterAction()掀虎。

2.2 源碼分析

2.2.1 處理 --dry-run

RunTasks 的過(guò)程發(fā)生在 DefaultGradleLauncherrunWork() 中,先來(lái)看看其源碼付枫。

// DefaultGradleLauncher.java
private void runWork() {
    // ...
    List<Throwable> taskFailures = new ArrayList<Throwable>();
    buildExecuter.execute(gradle, taskFailures);
    // ...
}

這里調(diào)用了 buildExecuterexecute()烹玉,而 buildExecuter 是通過(guò)反射調(diào)用GradleScopeServicescreateBuildExecuter() 生成的。

// GradleScopeServices.java
BuildWorkExecutor createBuildExecuter(StyledTextOutputFactory textOutputFactory, IncludedBuildControllers includedBuildControllers, BuildOperationExecutor buildOperationExecutor) {
    return new BuildOperationFiringBuildWorkerExecutor(
        new IncludedBuildLifecycleBuildWorkExecutor(
            new DefaultBuildWorkExecutor(
                // 記住這兩個(gè) BuildExecutionAction
                asList(new DryRunBuildExecutionAction(textOutputFactory),
                    new SelectedTaskExecutionAction())),
            includedBuildControllers),
        buildOperationExecutor);
}

這里有兩個(gè)比較重要的 BuildExecutionAction阐滩,暫時(shí)先記住它們:

  • DryRunBuildExecutionAction
  • SelectedTaskExecutionAction

上面的代碼最終會(huì)調(diào)用到 DefaultBuildWorkExecutorexecute()二打,來(lái)看看其源碼。

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

// 和 TaskGraph 階段的 BuildConfigurationAction 執(zhí)行差不多
private void execute(final GradleInternal gradle, final int index, final Collection<? super Throwable> taskFailures) {
    if (index >= executionActions.size()) {
        return;
    }
    executionActions.get(index).execute(new BuildExecutionContext() {
        @Override
        public GradleInternal getGradle() {
            return gradle;
        }

        @Override
        public void proceed() {
            execute(gradle, index + 1, taskFailures);
        }

    }, taskFailures);
}

這里遍歷執(zhí)行了傳給 DefaultBuildWorkExecutor 構(gòu)造器的 BuildConfigurationActionexecute()掂榔,也就是前面提到的 DryRunBuildExecutionActionSelectedTaskExecutionAction继效。來(lái)看看 DryRunBuildExecutionActionexecute() 做了什么症杏。

// DryRunBuildExecutionAction.java
public void execute(BuildExecutionContext context, Collection<? super Throwable> taskFailures) {
    GradleInternal gradle = context.getGradle();
    // 判斷是否有指定參數(shù) -m 或者 --dry-run
    if (gradle.getStartParameter().isDryRun()) {
        for (Task task : gradle.getTaskGraph().getAllTasks()) {
            // 如果有指定,則直接攔截task的執(zhí)行瑞信,改為打印 task 的 name 以及執(zhí)行順序
            textOutputFactory.create(DryRunBuildExecutionAction.class)
                .append(((TaskInternal) task).getIdentityPath().getPath())
                .append(" ")
                .style(StyledTextOutput.Style.ProgressStatus)
                .append("SKIPPED")
                .println();
        }
    } else {
        // 3. 如果沒有配置厉颤,則執(zhí)行下一個(gè) BuildExecutionAction 的 execute()
        context.proceed();
    }
}

可以看到 DryRunBuildExecutionAction 的作用是攔截 task 的執(zhí)行過(guò)程。

  1. 首先通過(guò) StartParameter 獲取到是否有指定 -m 或者 --dry-run 參數(shù)凡简;
  2. 如果有指定該參數(shù)逼友,則攔截 tasks 的執(zhí)行,改為遍歷所有待執(zhí)行的 tasks秤涩,逐個(gè)打印其 path帜乞;
  3. 如果沒有指定該參數(shù),則執(zhí)行下一個(gè) BuildExecutionActionexecute()筐眷。

來(lái)看看 ./gradlew clean --dry-run 的效果圖挖函。

--dry-run效果圖.png

2.2.2 回調(diào)傳給 whenReady() 的閉包

接下來(lái)會(huì)執(zhí)行到 SelectedTaskExecutionActionexecute(),來(lái)看看其源碼浊竟。

// SelectedTaskExecutionAction.java
public void execute(BuildExecutionContext context, Collection<? super Throwable> taskFailures) {
    GradleInternal gradle = context.getGradle();
    TaskExecutionGraphInternal taskGraph = gradle.getTaskGraph();
    // 是否有指定參數(shù) --continue怨喘,如果為true,在失敗的時(shí)候依舊會(huì)繼續(xù)執(zhí)行
    if (gradle.getStartParameter().isContinueOnFailure()) {
        taskGraph.setContinueOnFailure(true);
    }

    taskGraph.addTaskExecutionGraphListener(new BindAllReferencesOfProjectsToExecuteListener());
    // 執(zhí)行 tasks
    taskGraph.execute(taskFailures);
}

這里首先會(huì)看是否有指定 --continue振定,該參數(shù)表示在執(zhí)行失敗的時(shí)候是否繼續(xù)執(zhí)行 tasks必怜,然后調(diào)用 DefaultTaskExecutionGraphexecute() 準(zhǔn)備 run tasks。

// DefaultTaskExecutionGraph.java
public void execute(Collection<? super Throwable> failures) {
    ProjectExecutionServiceRegistry projectExecutionServices = new ProjectExecutionServiceRegistry();
    executeWithServices(projectExecutionServices, failures);
    // ...
}

private void executeWithServices(ProjectExecutionServiceRegistry projectExecutionServices, Collection<? super Throwable> failures) {
    Timer clock = Time.startTimer();
    // 1. 確保task的有向無(wú)環(huán)圖已經(jīng)生成
    ensurePopulated();
    if (!hasFiredWhenReady) {
        ProjectStateRegistry projectStateRegistry = gradleInternal.getServices().get(ProjectStateRegistry.class);
        // 2. 調(diào)用 TaskExecutionGraphListener 的 graphPopulated()
        projectStateRegistry.withLenientState(new Runnable() {
            @Override
            public void run() {
                buildOperationExecutor.run(new NotifyTaskGraphWhenReady(DefaultTaskExecutionGraph.this, graphListeners.getSource(), gradleInternal));
            }
        });
        hasFiredWhenReady = true;
    } 

    try {
        // 3. 調(diào)用 DefaultPlanExecutor的process()
        planExecutor.process(executionPlan, failures,
            new BuildOperationAwareExecutionAction(
                buildOperationExecutor.getCurrentOperation(),
                new InvokeNodeExecutorsAction(nodeExecutors, projectExecutionServices)
            )
        );
    }
    // ...
}

這里首先調(diào)用了 ensurePopulated() 確保 task 的有向無(wú)環(huán)圖已經(jīng)生成后频,然后會(huì)調(diào)用 NotifyTaskGraphWhenReadyrun()梳庆,來(lái)看看其源碼。

// NotifyTaskGraphWhenReady(DefaultTaskExecutionGraph的內(nèi)部類)
public void run(BuildOperationContext context) {
    graphListener.graphPopulated(taskExecutionGraph);
}

這里會(huì)調(diào)用 TaskExecutionGraphListenergraphPopulated()卑惜;為什么提這個(gè)方法膏执,這就得看看 DefaultTaskExecutionGraphwhenReady() 了,這也是編寫 gradle 腳本經(jīng)常使用的一個(gè)方法露久。

// DefaultTaskExecutionGraph.java
public void whenReady(final Closure closure) {
    graphListeners.add(new ClosureBackedMethodInvocationDispatch("graphPopulated", listenerBuildOperationDecorator.decorate("TaskExecutionGraph.whenReady", closure)));
}

public void whenReady(final Action<TaskExecutionGraph> action) {
    graphListeners.add(listenerBuildOperationDecorator.decorate("TaskExecutionGraph.whenReady", TaskExecutionGraphListener.class, new TaskExecutionGraphListener() {
        @Override
        public void graphPopulated(TaskExecutionGraph graph) {
            action.execute(graph);
        }
    }));
}

可以看到更米,傳給 whenReady() 的動(dòng)作實(shí)際上是被封裝成了 TaskExecutionGraphListener,所以調(diào)用 TaskExecutionGraphListenergraphPopulated() 即回調(diào)了傳給 whenReady() 的動(dòng)作毫痕。

接著調(diào)用了 planExecutorprocess()征峦,注意這里傳遞的參數(shù) BuildOperationAwareExecutionAction,后面會(huì)使用到消请。

2.2.3 創(chuàng)建線程和 ExecutorWorker

planExecutor 是通過(guò)反射調(diào)用的 ExecutionGradleServicescreatePlanExecutor() 栏笆。

// ExecutionGradleServices.java
PlanExecutor createPlanExecutor(
    ParallelismConfigurationManager parallelismConfigurationManager,
    ExecutorFactory executorFactory,
    WorkerLeaseService workerLeaseService,
    BuildCancellationToken cancellationToken,
    ResourceLockCoordinationService coordinationService) {
    // 這個(gè)參數(shù)gradle并行構(gòu)建的時(shí)候會(huì)有用 org.gradle.parallel = true
    int parallelThreads = parallelismConfigurationManager.getParallelismConfiguration().getMaxWorkerCount();
    if (parallelThreads < 1) {
        throw new IllegalStateException(String.format("Cannot create executor for requested number of worker threads: %s.", parallelThreads));
    }

    return new DefaultPlanExecutor(
        parallelismConfigurationManager.getParallelismConfiguration(),
        executorFactory,
        workerLeaseService,
        cancellationToken,
        coordinationService
    );
}

DefaultPlanExecutor 的實(shí)例,來(lái)看看其 process() 的源碼臊泰。

// DefaultPlanExecutor.java
public void process(ExecutionPlan executionPlan, Collection<? super Throwable> failures, Action<Node> nodeExecutor) {
    // 創(chuàng)建線程池
    ManagedExecutor executor = executorFactory.create("Execution worker for '" + executionPlan.getDisplayName() + "'");
    try {
        WorkerLease parentWorkerLease = workerLeaseService.getCurrentWorkerLease();
        // org.gradle.parallel=true 的時(shí)候會(huì)開啟多個(gè) ExecutorWorker 并行構(gòu)建
        startAdditionalWorkers(executionPlan, nodeExecutor, executor, parentWorkerLease);
        new ExecutorWorker(executionPlan, nodeExecutor, parentWorkerLease, cancellationToken, coordinationService).run();
        awaitCompletion(executionPlan, failures);
    }
    // ...
}

private void startAdditionalWorkers(ExecutionPlan executionPlan, Action<? super Node> nodeExecutor, Executor executor, WorkerLease parentWorkerLease) {
    // 創(chuàng)建多個(gè) ExecutorWorker 并行構(gòu)建
    for (int i = 1; i < executorCount; i++) {
        executor.execute(new ExecutorWorker(executionPlan, nodeExecutor, parentWorkerLease, cancellationToken, coordinationService));
    }
}

這里會(huì)創(chuàng)建線程池 ManagedExecutor 和任務(wù) ExecutorWorker蛉加,在開啟了 org.gradle.parallel 的情況下,會(huì)創(chuàng)建多個(gè)線程和任務(wù)并行執(zhí)行。

2.2.4 task 執(zhí)行前的預(yù)處理

接著會(huì)調(diào)用到 ExecutorWorkerrun()针饥,來(lái)看看其源碼祟偷。

// ExecutorWorker(DefaultPlanExecutor.java的內(nèi)部類)
public void run() {
    WorkerLease childLease = parentWorkerLease.createChild();
    while (true) {
        // 調(diào)用 executeNextNode()
        boolean nodesRemaining = executeNextNode(childLease, new Action<Node>() {
            @Override
            public void execute(Node work) {
                nodeExecutor.execute(work);
                // ...
            }
        });
        if (!nodesRemaining) {
            // 沒有任務(wù)執(zhí)行了。
            break;
        }
    }
}

private boolean executeNextNode(final WorkerLease workerLease, final Action<Node> nodeExecutor) {
    final MutableReference<Node> selected = MutableReference.empty();
    final MutableBoolean nodesRemaining = new MutableBoolean();
    coordinationService.withStateLock(new Transformer<ResourceLockState.Disposition, ResourceLockState>() {
        @Override
        public ResourceLockState.Disposition transform(ResourceLockState resourceLockState) {
            // 是否取消執(zhí)行
            if (cancellationToken.isCancellationRequested()) {
                executionPlan.cancelExecution();
            }

            nodesRemaining.set(executionPlan.hasNodesRemaining());
            // 沒有任務(wù)執(zhí)行了打厘,則標(biāo)記為結(jié)束
            if (!nodesRemaining.get()) {
                return FINISHED;
            }

            try {
                selected.set(executionPlan.selectNext(workerLease, resourceLockState));
            } catch (Throwable t) {
                resourceLockState.releaseLocks();
                executionPlan.abortAllAndFail(t);
                nodesRemaining.set(false);
            }

            if (selected.get() == null && nodesRemaining.get()) {
                return RETRY;
            } else {
                return FINISHED;
            }
        }
    });

    Node selectedNode = selected.get();
    if (selectedNode != null) {
        execute(selectedNode, workerLease, nodeExecutor);
    }
    return nodesRemaining.get();
}

private void execute(final Node selected, final WorkerLease workerLease, Action<Node> nodeExecutor) {
    try {
        if (!selected.isComplete()) {
            try {
                // 執(zhí)行 ExecutorWorker里面創(chuàng)建的 Action 匿名內(nèi)部類實(shí)例的 execute()
                nodeExecutor.execute(selected);
            } catch (Throwable e) {
                selected.setExecutionFailure(e);
            }
        }
    }
    // ...
}

可以看到最終會(huì)調(diào)用到 nodeExecutor.execute(work)修肠,而這里的 nodeExecutor 也就是前面說(shuō)的傳給 process()BuildOperationAwareExecutionAction 的實(shí)例,來(lái)看看其 execute()户盯。

public void execute(Node node) {
    // ...
    delegate.execute(node);
    // ...
}

這里實(shí)際上是調(diào)用了 InvokeNodeExecutorsActionexecute()嵌施。

public void execute(Node node) {
    for (NodeExecutor nodeExecutor : nodeExecutors) {
        if (nodeExecutor.execute(node, projectExecutionServices)) {
            return;
        }
    }
    throw new IllegalStateException("Unknown type of node: " + node);
}

可以看到它只是遍歷調(diào)用了傳遞進(jìn)來(lái)的 nodeExecutorexecute();這里的 nodeExecutors 是通過(guò)反射調(diào)用了 GradleScopeServicescreateLocalTaskNodeExecutor()莽鸭。

// GradleScopeServices.java
LocalTaskNodeExecutor createLocalTaskNodeExecutor() {
    return new LocalTaskNodeExecutor();
}

LocalTaskNodeExecutor 的實(shí)例吗伤,來(lái)看看其 execute() 的源碼。

// LocalTaskNodeExecutor.java
public boolean execute(Node node, ProjectExecutionServiceRegistry services) {
    if (node instanceof LocalTaskNode) {
        LocalTaskNode localTaskNode = (LocalTaskNode) node;
        TaskInternal task = localTaskNode.getTask();
        TaskStateInternal state = task.getState();
        // 判斷任務(wù)是否已經(jīng)執(zhí)行過(guò)硫眨,如果執(zhí)行過(guò)足淆,則直接返回
        if (state.getExecuted()) {
            return true;
        }
        TaskExecutionContext ctx = new DefaultTaskExecutionContext(localTaskNode);
        // 這里又通過(guò)反射找 TaskExecuter
        TaskExecuter taskExecuter = services.getProjectService((ProjectInternal) task.getProject(), TaskExecuter.class);
        assert taskExecuter != null;
        // 這里就是執(zhí)行 task 的入口
        taskExecuter.execute(task, state, ctx);
        localTaskNode.getPostAction().execute(task);
        return true;
    } else {
        return false;
    }
}

它首先判斷 task 是否有執(zhí)行過(guò),如果有執(zhí)行過(guò)則直接返回礁阁;如果沒有執(zhí)行過(guò)巧号,則調(diào)用 TaskExecuterexecute() 執(zhí)行 task。taskExecuter 是通過(guò)反射調(diào)用的 ProjectExecutionServicescreateTaskExecuter()姥闭。

// ProjectExecutionServices.java
TaskExecuter createTaskExecuter(TaskExecutionModeResolver repository,
                                BuildCacheController buildCacheController,
                                TaskInputsListener inputsListener,
                                TaskActionListener actionListener,
                                OutputChangeListener outputChangeListener,
                                ClassLoaderHierarchyHasher classLoaderHierarchyHasher,
                                TaskSnapshotter taskSnapshotter,
                                FileCollectionFingerprinterRegistry fingerprinterRegistry,
                                BuildOperationExecutor buildOperationExecutor,
                                AsyncWorkTracker asyncWorkTracker,
                                BuildOutputCleanupRegistry cleanupRegistry,
                                ExecutionHistoryStore executionHistoryStore,
                                OutputFilesRepository outputFilesRepository,
                                BuildScanPluginApplied buildScanPlugin,
                                FileCollectionFactory fileCollectionFactory,
                                PropertyWalker propertyWalker,
                                TaskExecutionGraphInternal taskExecutionGraph,
                                TaskExecutionListener taskExecutionListener,
                                TaskListenerInternal taskListenerInternal,
                                TaskCacheabilityResolver taskCacheabilityResolver,
                                WorkExecutor<AfterPreviousExecutionContext, CachingResult> workExecutor,
                                ReservedFileSystemLocationRegistry reservedFileSystemLocationRegistry,
                                ListenerManager listenerManager
) {

    boolean buildCacheEnabled = buildCacheController.isEnabled();
    boolean scanPluginApplied = buildScanPlugin.isBuildScanPluginApplied();
    // 這個(gè) executer 才是真正執(zhí)行 task 的
    TaskExecuter executer = new ExecuteActionsTaskExecuter(
        buildCacheEnabled,
        scanPluginApplied,
        taskSnapshotter,
        executionHistoryStore,
        buildOperationExecutor,
        asyncWorkTracker,
        actionListener,
        taskCacheabilityResolver,
        fingerprinterRegistry,
        classLoaderHierarchyHasher,
        workExecutor,
        listenerManager
    );
    // 下面這些都是包裝
    executer = new ValidatingTaskExecuter(executer, reservedFileSystemLocationRegistry);
    executer = new SkipEmptySourceFilesTaskExecuter(inputsListener, executionHistoryStore, cleanupRegistry, outputChangeListener, executer);
    executer = new ResolveBeforeExecutionOutputsTaskExecuter(taskSnapshotter, executer);
    if (buildCacheEnabled || scanPluginApplied) {
        executer = new StartSnapshotTaskInputsBuildOperationTaskExecuter(buildOperationExecutor, executer);
    }
    executer = new ResolveAfterPreviousExecutionStateTaskExecuter(executionHistoryStore, executer);
    executer = new CleanupStaleOutputsExecuter(cleanupRegistry, outputFilesRepository, buildOperationExecutor, outputChangeListener, executer);
    executer = new FinalizePropertiesTaskExecuter(executer);
    executer = new ResolveTaskExecutionModeExecuter(repository, fileCollectionFactory, propertyWalker, executer);
    executer = new SkipTaskWithNoActionsExecuter(taskExecutionGraph, executer);
    executer = new SkipOnlyIfTaskExecuter(executer);
    executer = new CatchExceptionTaskExecuter(executer);
    executer = new EventFiringTaskExecuter(buildOperationExecutor, taskExecutionListener, taskListenerInternal, executer);
    return executer;
}

真正執(zhí)行 task 的是 ExecuteActionsTaskExecuter丹鸿,其他都是對(duì)其進(jìn)行的包裝,在執(zhí)行 task 前做一些預(yù)處理操作棚品,從下往上挑關(guān)鍵的說(shuō)靠欢。

2.2.4.1 EventFiringTaskExecuter

首先來(lái)看看 EventFiringTaskExecuterexecute()

// EventFiringTaskExecuter.java
public TaskExecuterResult execute(final TaskInternal task, final TaskStateInternal state, final TaskExecutionContext context) {
    return buildOperationExecutor.call(new CallableBuildOperation<TaskExecuterResult>() {
        @Override
        public TaskExecuterResult call(BuildOperationContext operationContext) {
            TaskExecuterResult result = executeTask(operationContext);
            // ...
            return result;
        }

        private TaskExecuterResult executeTask(BuildOperationContext operationContext) {
            // ... 
            // 1. 調(diào)用 TaskExecutionListener 的 beforeExecute()
            taskExecutionListener.beforeExecute(task);
            // ...
            // 2. 執(zhí)行下一個(gè) execute()
            TaskExecuterResult result = delegate.execute(task, state, context);
            // ... 
            // 3. 調(diào)用 TaskExecutionListener 的 afterExecute()
            taskExecutionListener.afterExecute(task, state);
            // ...
        }
    });
}

可以看到铜跑,這里主要是增加事件回調(diào)门怪。在 Task 執(zhí)行前調(diào)用 TaskExecutionListenerbeforeExecute(),在 Task 執(zhí)行后調(diào)用 TaskExecutionListenerafterExecute()锅纺。

2.2.4.2 CatchExceptionTaskExecuter

再來(lái)看看 CatchExceptionTaskExecuterexecute()掷空。

// CatchExceptionTaskExecuter.java
public TaskExecuterResult execute(TaskInternal task, TaskStateInternal state, TaskExecutionContext context) {
    try {
        return delegate.execute(task, state, context);
    } catch (RuntimeException e) {
        state.setOutcome(new TaskExecutionException(task, e));
        return TaskExecuterResult.WITHOUT_OUTPUTS;
    }
}

這里主要是給 task 執(zhí)行加上 try{}catch{}

2.2.4.3 SkipOnlyIfTaskExecuter

再來(lái)看看 SkipOnlyIfTaskExecuterexecute()伞广。

// SkipOnlyIfTaskExecuter.java
public TaskExecuterResult execute(TaskInternal task, TaskStateInternal state, TaskExecutionContext context) {
    boolean skip;
    try {
        skip = !task.getOnlyIf().isSatisfiedBy(task);
    } catch (Throwable t) {
        state.setOutcome(new GradleException(String.format("Could not evaluate onlyIf predicate for %s.", task), t));
        return TaskExecuterResult.WITHOUT_OUTPUTS;
    }

    if (skip) {
        state.setOutcome(TaskExecutionOutcome.SKIPPED);
        return TaskExecuterResult.WITHOUT_OUTPUTS;
    }

    return executer.execute(task, state, context);
}

這里主要是判斷 task 的 onlyIf 條件是否滿足執(zhí)行拣帽,onlyIf 類似于 javaif 語(yǔ)句疼电,只有當(dāng)判斷條件為真的時(shí)候才會(huì)執(zhí)行 task嚼锄。

舉個(gè)栗子方便理解。在 root project 的 build.gradle 文件里面添加如下代碼蔽豺。

subprojects { Project p ->
    Task hello = p.task("hello") {
        doLast {
            println("execute hello task!")
        }
    }
}

sync 后運(yùn)行 ./gradlew hello 区丑,結(jié)果如下。

沒有onlyIf.png

這里分別執(zhí)行了 app 和 app2 的 hello task,然后修改 build.gradle 增加 onlyIf 判斷沧侥。

subprojects { Project p ->
    Task hello = p.task("hello") {
        doLast {
            println("execute hello task!")
        }
    }
    // 只有當(dāng)是 app 的時(shí)候才執(zhí)行
    hello.onlyIf { hello.project.name == "app" }
}

sync 后再次運(yùn)行 ./gradlew hello 可霎,結(jié)果如下,可以看到相較于上面少了 :app2:hello 的執(zhí)行宴杀,說(shuō)明 onlyIf 生效了癣朗。

有onlyIf.png

2.2.4.4 SkipTaskWithNoActionsExecuter

來(lái)看看 SkipTaskWithNoActionsExecuterexecute()

// SkipTaskWithNoActionsExecuter.java
public TaskExecuterResult execute(TaskInternal task, TaskStateInternal state, TaskExecutionContext context) {
    if (!task.hasTaskActions()) {
        boolean upToDate = true;
        for (Task dependency : taskExecutionGraph.getDependencies(task)) {
            if (!dependency.getState().getSkipped()) {
                upToDate = false;
                break;
            }
        }
        state.setActionable(false);
        state.setOutcome(upToDate ? TaskExecutionOutcome.UP_TO_DATE : TaskExecutionOutcome.EXECUTED);
        return TaskExecuterResult.WITHOUT_OUTPUTS;
    }
    return executer.execute(task, state, context);
}

這里是跳過(guò)那些沒有 action 的 task旺罢,沒有 action 說(shuō)明 task 不需要執(zhí)行旷余。

2.2.4.5 ResolveTaskExecutionModeExecuter

來(lái)看看 ResolveTaskExecutionModeExecuterexecute()

// ResolveTaskExecutionModeExecuter.java
public TaskExecuterResult execute(final TaskInternal task, TaskStateInternal state, final TaskExecutionContext context) {
    Timer clock = Time.startTimer();
    // 1. 解析 task 屬性
    TaskProperties properties = DefaultTaskProperties.resolve(propertyWalker, fileCollectionFactory, task);
    context.setTaskProperties(properties);
    // 2. 解析 task 的 Execution Mode
    TaskExecutionMode taskExecutionMode = executionModeResolver.getExecutionMode(task, properties);
    TaskOutputsInternal outputs = task.getOutputs();
    context.setTaskExecutionMode(taskExecutionMode);
    // ...
}

這里主要做了兩件事情:

  1. 解析 Task 的屬性扁达,比如輸入正卧、輸出等;
  2. 獲取 TaskExecution Mode跪解;

過(guò)程一有點(diǎn)多炉旷,先說(shuō)過(guò)程二。這里的 executionModeResolver 是通過(guò)反射調(diào)用 ProjectExecutionServicescreateExecutionModeResolver()叉讥。

TaskExecutionModeResolver createExecutionModeResolver(
    StartParameter startParameter
) {
    return new DefaultTaskExecutionModeResolver(startParameter);
}

來(lái)看看 DefaultTaskExecutionModeResolvergetExecutionMode()窘行。

// DefaultTaskExecutionModeResolver.java
public TaskExecutionMode getExecutionMode(TaskInternal task, TaskProperties properties) {
    AndSpec<? super TaskInternal> upToDateSpec = task.getOutputs().getUpToDateSpec();
    // 如果沒有聲明 outputs 并且沒有指定 upToDateSpec
    if (!properties.hasDeclaredOutputs() && upToDateSpec.isEmpty()) {
        if (task.hasTaskActions()) {
            if (requiresInputChanges(task)) {
                DeprecationLogger.nagUserOfDeprecated("Using the incremental task API without declaring any outputs", "Please declare output files for your task or use `TaskOutputs.upToDateWhen()`.");
            } else {
                return TaskExecutionMode.NO_OUTPUTS_WITH_ACTIONS;
            }
        } else {
            return TaskExecutionMode.NO_OUTPUTS_WITHOUT_ACTIONS;
        }
    }

    if (startParameter.isRerunTasks()) {
        return TaskExecutionMode.RERUN_TASKS_ENABLED;
    }

    if (!upToDateSpec.isSatisfiedBy(task)) {
        return TaskExecutionMode.UP_TO_DATE_WHEN_FALSE;
    }

    return TaskExecutionMode.INCREMENTAL;
}

這個(gè) TaskExecutionMode 究竟是啥玩意呢?來(lái)看看其源碼图仓。

public enum TaskExecutionMode {
    INCREMENTAL(null, true, true),
    NO_OUTPUTS_WITHOUT_ACTIONS("Task has not declared any outputs nor actions.", false, false),
    NO_OUTPUTS_WITH_ACTIONS("Task has not declared any outputs despite executing actions.", false, false),
    RERUN_TASKS_ENABLED("Executed with '--rerun-tasks'.", true, false),
    UP_TO_DATE_WHEN_FALSE("Task.upToDateWhen is false.", true, false);

    @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
    private final Optional<String> rebuildReason;
    private final boolean taskHistoryMaintained;
    private final boolean allowedToUseCachedResults;

    TaskExecutionMode(@Nullable String rebuildReason, boolean taskHistoryMaintained, boolean allowedToUseCachedResults) {
        this.rebuildReason = Optional.ofNullable(rebuildReason);
        this.taskHistoryMaintained = taskHistoryMaintained;
        this.allowedToUseCachedResults = allowedToUseCachedResults;
    }

    // 返回原因
    public Optional<String> getRebuildReason() {
        return rebuildReason;
    }

    // 這個(gè)方法標(biāo)記了是否需要記錄執(zhí)行歷史
    public boolean isTaskHistoryMaintained() {
        return taskHistoryMaintained;
    }

    // 這里方法決定了是否加載緩存來(lái)替代執(zhí)行 task
    public boolean isAllowedToUseCachedResults() {
        return allowedToUseCachedResults;
    }
}

TaskExecutionMode 有兩個(gè)比較重要的方法 isTaskHistoryMaintained()isAllowedToUseCachedResults()抽高,它們影響到了 Task 的執(zhí)行流程。

再看下過(guò)程一是如何解析 Task 屬性的透绩。先來(lái)看看DefaultTaskPropertiesresolve()翘骂。

// DefaultTaskProperties.java
public static TaskProperties resolve(PropertyWalker propertyWalker, FileCollectionFactory fileCollectionFactory, TaskInternal task) {
    String beanName = task.toString();
    GetInputFilesVisitor inputFilesVisitor = new GetInputFilesVisitor(beanName, fileCollectionFactory);
    GetOutputFilesVisitor outputFilesVisitor = new GetOutputFilesVisitor(beanName, fileCollectionFactory);
    GetInputPropertiesVisitor inputPropertiesVisitor = new GetInputPropertiesVisitor(beanName);
    GetLocalStateVisitor localStateVisitor = new GetLocalStateVisitor(beanName, fileCollectionFactory);
    GetDestroyablesVisitor destroyablesVisitor = new GetDestroyablesVisitor(beanName, fileCollectionFactory);
    ValidationVisitor validationVisitor = new ValidationVisitor();
    try {
        // 主要是這個(gè)方法
        TaskPropertyUtils.visitProperties(propertyWalker, task, new CompositePropertyVisitor(
            inputPropertiesVisitor,
            inputFilesVisitor,
            outputFilesVisitor,
            validationVisitor,
            destroyablesVisitor,
            localStateVisitor
        ));
    } catch (Exception e) {
        throw new TaskExecutionException(task, e);
    }

    // 把解析出來(lái)的屬性存到 DefaultTaskProperties里面
    return new DefaultTaskProperties(
        task.toString(),
        inputPropertiesVisitor.getPropertyValuesSupplier(),
        inputFilesVisitor.getFileProperties(),
        outputFilesVisitor.getFileProperties(),
        outputFilesVisitor.hasDeclaredOutputs(),
        localStateVisitor.getFiles(),
        destroyablesVisitor.getFiles(),
        validationVisitor.getTaskPropertySpecs());
}

主要是調(diào)用的 TaskPropertyUtils.visitProperties(),來(lái)看看其源碼帚豪。

// TaskPropertyUtils.java
public static void visitProperties(PropertyWalker propertyWalker, final TaskInternal task, final PropertyVisitor visitor) {
    StrictErrorsOnlyContext validationContext = new StrictErrorsOnlyContext(task);
    propertyWalker.visitProperties(task, validationContext, visitor);
    // ...
}

這里的 propertyWalker 是通過(guò)反射調(diào)用的 ExecutionGlobalServicescreatePropertyWalker()碳竟。

// ExecutionGlobalServices.java
PropertyWalker createPropertyWalker(TaskScheme taskScheme) {
    return taskScheme.getInspectionScheme().getPropertyWalker();
}

taskScheme 是通過(guò)反射調(diào)用的 ExecutionGlobalServicescreateTaskScheme()

// ExecutionGlobalServices.java
TaskScheme createTaskScheme(InspectionSchemeFactory inspectionSchemeFactory, InstantiatorFactory instantiatorFactory) {
    InstantiationScheme instantiationScheme = instantiatorFactory.decorateScheme();
    InspectionScheme inspectionScheme = inspectionSchemeFactory.inspectionScheme(
        ImmutableSet.of(
            Input.class,
            InputFile.class,
            InputFiles.class,
            InputDirectory.class,
            OutputFile.class,
            OutputFiles.class,
            OutputDirectory.class,
            OutputDirectories.class,
            Destroys.class,
            LocalState.class,
            Nested.class,
            Console.class,
            ReplacedBy.class,
            Internal.class,
            OptionValues.class
        ),
        ImmutableSet.of(
            Classpath.class,
            CompileClasspath.class,
            Incremental.class,
            Optional.class,
            PathSensitive.class,
            SkipWhenEmpty.class
        ),
        instantiationScheme);
    return new TaskScheme(instantiationScheme, inspectionScheme);
}

注意下傳給 inspectionScheme() 的第一個(gè)參數(shù)狸臣,是很多的注解莹桅,解析屬性會(huì)用到它們,后面再說(shuō)烛亦。先看下 InspectionSchemeFactory.InspectionSchemeImplgetPropertyWalker() 诈泼。

// InspectionSchemeFactory.java
private static class InspectionSchemeImpl implements InspectionScheme {
    private final DefaultPropertyWalker propertyWalker;

    public InspectionSchemeImpl(List<TypeAnnotationHandler> typeHandlers, List<PropertyAnnotationHandler> propertyHandlers, Collection<Class<? extends Annotation>> propertyModifiers, TypeAnnotationMetadataStore typeAnnotationMetadataStore, CrossBuildInMemoryCacheFactory cacheFactory) {
        propertyWalker = new DefaultPropertyWalker(metadataStore);
    }

    @Override
    public PropertyWalker getPropertyWalker() {
        return propertyWalker;
    }
}

DefaultPropertyWalker 的實(shí)例,來(lái)看看其源碼煤禽。

public class DefaultPropertyWalker implements PropertyWalker {
    private final RuntimeBeanNodeFactory nodeFactory;

    public DefaultPropertyWalker(TypeMetadataStore typeMetadataStore) {
        this.nodeFactory = new RuntimeBeanNodeFactory(typeMetadataStore);
    }

    @Override
    public void visitProperties(Object bean, ParameterValidationContext validationContext, PropertyVisitor visitor) {
        Queue<RuntimeBeanNode<?>> queue = new ArrayDeque<RuntimeBeanNode<?>>();
        // node 為 RootRuntimeBeanNode
        queue.add(nodeFactory.createRoot(bean));
        while (!queue.isEmpty()) {
            RuntimeBeanNode<?> node = queue.remove();
            node.visitNode(visitor, queue, nodeFactory, validationContext);
        }
    }
}

// RuntimeBeanNodeFactory.java
public RuntimeBeanNode<?> createRoot(Object bean) {
    return new RootRuntimeBeanNode(bean, metadataStore.getTypeMetadata(bean.getClass()));
}

這里的 nodeRootRuntimeBeanNode铐达,來(lái)看看其 visitNode()

// AbstractNestedRuntimeBeanNode.java
protected void visitProperties(PropertyVisitor visitor, final Queue<RuntimeBeanNode<?>> queue, final RuntimeBeanNodeFactory nodeFactory, ParameterValidationContext validationContext) {
    TypeMetadata typeMetadata = getTypeMetadata();
    typeMetadata.collectValidationFailures(getPropertyName(), validationContext);
    for (PropertyMetadata propertyMetadata : typeMetadata.getPropertiesMetadata()) {
        // 找屬性對(duì)應(yīng)的 PropertyAnnotationHandler
        PropertyAnnotationHandler annotationHandler = typeMetadata.getAnnotationHandlerFor(propertyMetadata);
        if (annotationHandler.shouldVisit(visitor)) {
            String propertyName = getQualifiedPropertyName(propertyMetadata.getPropertyName());
            PropertyValue value = new BeanPropertyValue(getBean(), propertyMetadata.getGetterMethod());
            // 這里最終會(huì)調(diào)用 注解對(duì)應(yīng)的 PropertyAnnotationHandler 的 visitPropertyValue()
            annotationHandler.visitPropertyValue(propertyName, value, propertyMetadata, visitor, new BeanPropertyContext() {
                @Override
                public void addNested(String propertyName, Object bean) {
                    queue.add(nodeFactory.create(AbstractNestedRuntimeBeanNode.this, propertyName, bean));
                }
            });
        }
    }
}

還記得前面很多注解的參數(shù)嗎檬果,其實(shí)解析屬性就是解析這些注解所修飾的東西瓮孙。每個(gè)注解都會(huì)對(duì)應(yīng)一個(gè) PropertyAnnotationHandler唐断。拿 InputFile 舉個(gè)栗子,它對(duì)應(yīng)的是 InputFilePropertyAnnotationHandler杭抠,來(lái)看看其 visitPropertyValue()脸甘。

// AbstractInputFilePropertyAnnotationHandler.java
public void visitPropertyValue(String propertyName, PropertyValue value, PropertyMetadata propertyMetadata, PropertyVisitor visitor, BeanPropertyContext context) {
    // ...
    // 調(diào)用了 visitor 的 visitInputFileProperty(),visitor 即前面 DefaultTaskProperties.resolve() 里面?zhèn)魅氲?GetInputFilesVisitor
    visitor.visitInputFileProperty(
        propertyName,
        propertyMetadata.isAnnotationPresent(Optional.class),
        propertyMetadata.isAnnotationPresent(SkipWhenEmpty.class),
        propertyMetadata.isAnnotationPresent(Incremental.class),
        fileNormalizer,
        value,
        getFilePropertyType()
    );
}

這里調(diào)用到了 visitorvisitInputFileProperty()偏灿,它是前面 DefaultTaskProperties.resolve() 里面?zhèn)魅氲?GetInputFilesVisitor 實(shí)例丹诀,來(lái)看看其 visitInputFileProperty()

public void visitInputFileProperty(final String propertyName, boolean optional, boolean skipWhenEmpty, boolean incremental, @Nullable Class<? extends FileNormalizer> fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) {
    // 解析 input file 是 directory 還是 file
    FileCollection actualValue = FileParameterUtils.resolveInputFileValue(fileCollectionFactory, filePropertyType, value);
    // 加到集合中
    specs.add(new DefaultInputFilePropertySpec(
        propertyName,
        FileParameterUtils.normalizerOrDefault(fileNormalizer),
        new PropertyFileCollection(ownerDisplayName, propertyName, "input", actualValue),
        value,
        skipWhenEmpty,
        incremental
    ));
    if (skipWhenEmpty) {
        hasSourceFiles = true;
    }
}

2.2.4.6 SkipEmptySourceFilesTaskExecuter

再來(lái)看看 SkipEmptySourceFilesTaskExecuterexecute()翁垂。

// SkipEmptySourceFilesTaskExecuter.java
public TaskExecuterResult execute(TaskInternal task, TaskStateInternal state, final TaskExecutionContext context) {
        TaskProperties properties = context.getTaskProperties();
        FileCollection sourceFiles = properties.getSourceFiles();
        // 如果有 source files 但是 source files 是空的
        if (properties.hasSourceFiles() && sourceFiles.isEmpty()) {
            AfterPreviousExecutionState previousExecution = context.getAfterPreviousExecution();
            ImmutableSortedMap<String, FileCollectionFingerprint> outputFiles = previousExecution == null
                ? ImmutableSortedMap.<String, FileCollectionFingerprint>of()
                : previousExecution.getOutputFileProperties();
            if (outputFiles.isEmpty()) {
                // 沒有 outputs忿墅,則標(biāo)記為 NO_SOURCE
                state.setOutcome(TaskExecutionOutcome.NO_SOURCE);
            } else {
                outputChangeListener.beforeOutputChange();
                OutputsCleaner outputsCleaner = new OutputsCleaner(new Predicate<File>() {
                    @Override
                    public boolean test(File file) {
                        return buildOutputCleanupRegistry.isOutputOwnedByBuild(file);
                    }
                }, new Predicate<File>() {
                    @Override
                    public boolean test(File dir) {
                        return buildOutputCleanupRegistry.isOutputOwnedByBuild(dir);
                    }
                });
                for (FileCollectionFingerprint outputFingerprints : outputFiles.values()) {
                    try {
                        outputsCleaner.cleanupOutputs(outputFingerprints);
                    } catch (IOException e) {
                        throw new UncheckedIOException(e);
                    }
                }
                if (outputsCleaner.getDidWork()) {
                    state.setOutcome(TaskExecutionOutcome.EXECUTED);
                } else {
                    state.setOutcome(TaskExecutionOutcome.NO_SOURCE);
                }
            }
            taskInputsListener.onExecute(task, Cast.cast(FileCollectionInternal.class, sourceFiles));
            executionHistoryStore.remove(task.getPath());
            return TaskExecuterResult.WITHOUT_OUTPUTS;
        } else {
            taskInputsListener.onExecute(task, Cast.cast(FileCollectionInternal.class, properties.getInputFiles()));
        }
        return executer.execute(task, state, context);
    }

這里是處理那些有設(shè)置 sourc files 但是 source files 為空的 Task,source files 為空說(shuō)明 Task 沒有需要處理的資源沮峡。

2.2.4.7 ValidatingTaskExecuter

再來(lái)看看 ValidatingTaskExecuterexecute()疚脐。

// ValidatingTaskExecuter.java
public TaskExecuterResult execute(TaskInternal task, TaskStateInternal state, TaskExecutionContext context) {
    List<String> messages = Lists.newArrayList();
    FileResolver resolver = ((ProjectInternal) task.getProject()).getFileResolver();
    final TaskValidationContext validationContext = new DefaultTaskValidationContext(resolver, reservedFileSystemLocationRegistry, messages);
    // 做一些屬性的校驗(yàn)操作
    context.getTaskProperties().validate(validationContext);

    if (!messages.isEmpty()) {
        List<String> firstMessages = messages.subList(0, Math.min(5, messages.size()));
        report(task, firstMessages, state);
        return TaskExecuterResult.WITHOUT_OUTPUTS;
    }

    return executer.execute(task, state, context);
}

這里是在 Task 執(zhí)行前做一些校驗(yàn)。

2.2.5 執(zhí)行 Task

最后會(huì)執(zhí)行到 ExecuteActionsTaskExecuterexecute()邢疙,這里才是正真執(zhí)行 Task 的地方棍弄,先來(lái)看看它的源碼。

// ExecuteActionsTaskExecuter.java
public TaskExecuterResult execute(TaskInternal task, TaskStateInternal state, TaskExecutionContext context) {
    // 創(chuàng)建一個(gè) TaskExecution 實(shí)例
    TaskExecution work = new TaskExecution(task, context, executionHistoryStore, fingerprinterRegistry, classLoaderHierarchyHasher);
    // 調(diào)用 workExecutor  的 execute疟游,最終會(huì)調(diào)用 getWork().execute()呼畸,即 TaskExecution 的 execute()
    CachingResult result = workExecutor.execute(new AfterPreviousExecutionContext() {
        @Override
        public UnitOfWork getWork() {
            return work;
        }
    });
    // ...
}

這里的 workExecutor 是通過(guò)反射調(diào)用的 ExecutionGradleServicescreateWorkExecutor()

// ExecutionGradleServices.java
public WorkExecutor<AfterPreviousExecutionContext, CachingResult> createWorkExecutor(
    BuildCacheCommandFactory buildCacheCommandFactory,
    BuildCacheController buildCacheController,
    BuildScanPluginApplied buildScanPlugin,
    BuildCancellationToken cancellationToken,
    BuildInvocationScopeId buildInvocationScopeId,
    ExecutionStateChangeDetector changeDetector,
    ClassLoaderHierarchyHasher classLoaderHierarchyHasher,
    ValueSnapshotter valueSnapshotter,
    OutputChangeListener outputChangeListener,
    OutputFilesRepository outputFilesRepository,
    TimeoutHandler timeoutHandler
) {
    return new DefaultWorkExecutor<AfterPreviousExecutionContext, CachingResult>(
        // 注意這里傳入的 Step 實(shí)例颁虐,最終會(huì)調(diào)用到 ExecuteStep 的 execute()
        new CaptureStateBeforeExecutionStep(classLoaderHierarchyHasher, valueSnapshotter,
            new ResolveCachingStateStep(buildCacheController, buildScanPlugin.isBuildScanPluginApplied(),
                new MarkSnapshottingInputsFinishedStep<UpToDateResult>(
                    new ResolveChangesStep<UpToDateResult>(changeDetector,
                        new SkipUpToDateStep<IncrementalChangesContext>(
                            new RecordOutputsStep<IncrementalChangesContext>(outputFilesRepository,
                                new StoreSnapshotsStep<IncrementalChangesContext>(
                                    new BroadcastChangingOutputsStep<IncrementalChangesContext, CurrentSnapshotResult>(outputChangeListener,
                                        new CacheStep(buildCacheController, buildCacheCommandFactory,
                                            new SnapshotOutputsStep<IncrementalChangesContext>(buildInvocationScopeId.getId(),
                                                new CreateOutputsStep<IncrementalChangesContext, Result>(
                                                    new CatchExceptionStep<IncrementalChangesContext>(
                                                        new TimeoutStep<IncrementalChangesContext>(timeoutHandler,
                                                            new CancelExecutionStep<IncrementalChangesContext>(cancellationToken,
                                                                new ResolveInputChangesStep<IncrementalChangesContext>(
                                                                    new CleanupOutputsStep<InputChangesContext, Result>(
                                                                        new ExecuteStep<InputChangesContext>()
                                                                    )
                                                                )
                                                            )
                                                        )
                                                    )
                                                )
                                            )
                                        )
                                    )
                                )
                            )
                        )
                    )
                )
            )
        )
    );
}

DefaultWorkExecutor 的實(shí)例蛮原,注意這里傳入的 Step,后面會(huì)用到另绩。先來(lái)看看 DefaultWorkExecutorexecute()儒陨。

// DefaultWorkExecutor.java
public R execute(C context) {
    return executeStep.execute(context);
}

這里直接調(diào)用了 executeStepexecute(),即上面?zhèn)魅氲?Stepexecute()笋籽,跟隨調(diào)用鏈發(fā)現(xiàn)它最終會(huì)調(diào)用到 ExecuteStepexecute()蹦漠,來(lái)看看其源碼。

// ExecuteStep.java
public Result execute(C context) {
    // 前面你說(shuō)了 getWork() 即 TaskExecution车海,這里調(diào)用了它的 execute()
    UnitOfWork work = context.getWork();
    ExecutionOutcome outcome = context.getInputChanges()
        .map(inputChanges -> determineOutcome(work.execute(inputChanges), inputChanges.isIncremental()))
        .orElseGet(() -> determineOutcome(work.execute(null), false));
    return new Result() {
        @Override
        public Try<ExecutionOutcome> getOutcome() {
            return Try.successful(outcome);
        }
    };
}

這里會(huì)調(diào)用 TaskExecutionexecute()笛园,來(lái)看看其源碼。

// TaskExecution(ExecuteActionsTaskExecuter.java的內(nèi)部類)
public WorkResult execute(@Nullable InputChangesInternal inputChanges) {
    task.getState().setExecuting(true);
    try {
        // 1. 調(diào)用 TaskActionListener 的 beforeActions()
        actionListener.beforeActions(task);
        // 2. 調(diào)用 executeActions()
        executeActions(task, inputChanges);
        return task.getState().getDidWork() ? WorkResult.DID_WORK : WorkResult.DID_NO_WORK;
    } finally {
        task.getState().setExecuting(false);
        // 3. 調(diào)用 TaskActionListener 的 afterActions()
        actionListener.afterActions(task);
    }
}

private void executeActions(TaskInternal task, @Nullable InputChangesInternal inputChanges) {
    boolean hasTaskListener = listenerManager.hasListeners(TaskActionListener.class) || listenerManager.hasListeners(TaskExecutionListener.class);
    Iterator<InputChangesAwareTaskAction> actions = new ArrayList<>(task.getTaskActions()).iterator();
    // 遍歷 actions侍芝,逐個(gè)調(diào)用 executeAction()
    while (actions.hasNext()) {
        InputChangesAwareTaskAction action = actions.next();
        task.getState().setDidWork(true);
        task.getStandardOutputCapture().start();
        boolean hasMoreWork = hasTaskListener || actions.hasNext();
        // 調(diào)用 executeAction()
        executeAction(action.getDisplayName(), task, action, inputChanges, hasMoreWork);
    }
}

private void executeAction(String actionDisplayName, TaskInternal task, InputChangesAwareTaskAction action, @Nullable InputChangesInternal inputChanges, boolean hasMoreWork) {
    if (inputChanges != null) {
        action.setInputChanges(inputChanges);
    }
    buildOperationExecutor.run(new RunnableBuildOperation() {
        @Override
        public void run(BuildOperationContext context) {
            // ...
            // 調(diào)用action 的execute()
            action.execute(task);
            // ...
        }
    });
}

這里的邏輯十分的清晰:

  1. 首先調(diào)用 TaskActionListenerbeforeActions()研铆;
  2. 然后遍歷 Task 所有的 Action ,逐個(gè)調(diào)用其 execute()(執(zhí)行 Task實(shí)際上就是執(zhí)行 Task 里面所有的 Action)州叠;
  3. 執(zhí)行完 Task 后會(huì)調(diào)用 TaskActionListenerafterActions()棵红。

執(zhí)行完 Task 后就會(huì)回到 DefaultGradleLauncherrunWork()

private void runWork() {
    // ...
    // 如果有失敗的留量,則拋出異常
    if (!taskFailures.isEmpty()) {
        throw new MultipleBuildFailures(taskFailures);
    }
    // 執(zhí)行成功則將狀態(tài)標(biāo)記為 RunTasks
    stage = Stage.RunTasks;
}

這里最后會(huì)將狀態(tài)標(biāo)記為 RunTasks窄赋,至此 Gradle 構(gòu)建流程的 RunTasks 就分析完了哟冬。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末楼熄,一起剝皮案震驚了整個(gè)濱河市忆绰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌可岂,老刑警劉巖错敢,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異缕粹,居然都是意外死亡稚茅,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門平斩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)亚享,“玉大人,你說(shuō)我怎么就攤上這事绘面∑鬯埃” “怎么了?”我有些...
    開封第一講書人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵揭璃,是天一觀的道長(zhǎng)晚凿。 經(jīng)常有香客問(wèn)我,道長(zhǎng)瘦馍,這世上最難降的妖魔是什么歼秽? 我笑而不...
    開封第一講書人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮情组,結(jié)果婚禮上燥筷,老公的妹妹穿的比我還像新娘。我一直安慰自己院崇,他們只是感情好荆责,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著亚脆,像睡著了一般做院。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上濒持,一...
    開封第一講書人閱讀 49,046評(píng)論 1 285
  • 那天键耕,我揣著相機(jī)與錄音,去河邊找鬼柑营。 笑死屈雄,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的官套。 我是一名探鬼主播酒奶,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼蚁孔,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了惋嚎?” 一聲冷哼從身側(cè)響起杠氢,我...
    開封第一講書人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎另伍,沒想到半個(gè)月后鼻百,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡摆尝,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年温艇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片堕汞。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡勺爱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出讯检,到底是詐尸還是另有隱情琐鲁,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布视哑,位于F島的核電站绣否,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏挡毅。R本人自食惡果不足惜蒜撮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望跪呈。 院中可真熱鬧段磨,春花似錦、人聲如沸耗绿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)误阻。三九已至债蜜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間究反,已是汗流浹背寻定。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留精耐,地道東北人狼速。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像卦停,于是被迫代替她去往敵國(guó)和親向胡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子恼蓬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容