Gradle Builds Everything——Task 實例

上文 講述了 Gradle 中關於任務的基礎概念,本文開始講述下 Task 是如何定義的。

為了方便,我們的語境分不開 <code>Gradle/<code>和<code>AndroidGradlePlugin/<code>,因此此處不脫離<code>Android/<code>環境來介紹<code>Gradle/<code>。我們在講述任務依賴的時候,提到一個<code>Manager/<code>的東西,在這裡,我們說到的是<code>AndroidGradlePlugin/<code>提供的<code>BuildableArtifactsHolder/<code>這個類。

一個 Task 如果有有意義的輸出,且產物可能被其他的 Task 所使用的時候,我們可以往 <code>BuildableArtifactsHolder/<code>註冊我們的產物,註冊方式有這麼幾種:

createBuildableArtifact/createDirectory/createArtifactFile

這些 api 需要傳入創建文件的類型,文件的文件名,動作等,以 <code>createArtifactFile/<code>的其中一種形式為例:

  1. <code>fun createArtifactFile(/<code>

  2. <code>artifactType: ArtifactType,/<code>

  3. <code>operationType: OperationType,/<code>

  4. <code>taskName: String,/<code>

  5. <code>fileName: String) : Provider/<code>

<code>artifactType/<code>就是產物類型

<code>operationType/<code>是操作類型,可以是初始化(init),追加(append),或者變化(transform),區別如下:

  1. 如果指明瞭是 init,那麼它之前不可以有任何針對相同產物類型的調用

  2. 如果指明瞭是 append,那麼是追加相關的文件

  3. 如果指明瞭是 transform,那麼就是替換當前的文件。

你可以根據你使用產物的目的來使用不同類型,因為返回值是一個 FileCollection (文件集合,不是文件夾的概念),如果調用的是 transform,你需要注意在 Configuration 階段對於這些產物調用順序的問題,如果 B.transform 在 A.transform 之後,那麼獲取最終產物的時候,就會取走 B 的結果。

BuildableArtifactsHolder 提供的 api 一般都已經讓你傳入了 taskName,就是讓你告訴它,你所產生的產物由哪個任務生成。後續你去根據 artifactType 獲取產物(FileCollection)的時候,它會檢查這個任務是否執行,如果沒有的話會先執行,這部分判斷的邏輯由 FileCollection 的 builtBy 做到,由 Gradle 進行管理。

Task 的配置

以上,我們介紹瞭如何讓 Task 的產物和 Task 本身產生一些關聯,這種關聯建立完成之後,可以看到 createArtifactFile 這個函數的返回值是 <code>Provider/<code>,這裡代表了一個目的地,我們往這個文件裡寫入的產物即可;當然這裡也可以創建文件夾同理,示例代碼:

  1. <code>task.outputFile = variantScope.getArtifacts.createArtifactFile(/<code>

  2. <code>InternalArtifactType.BUNDLE,/<code>

  3. <code>BuildArtifactsHolder.OperationType.INITIAL,/<code>

  4. <code>taskName,/<code>

  5. <code>bundleName)/<code>

然後在 task 定義的地方:

  1. <code>classTask {/<code>


  2. <code>private

    Provider outputFile;/<code>


  3. <code>@OutputFile/<code>

  4. <code>publicFlie getOutputFile {/<code>

  5. <code>returnoutputFile.get.asFile;/<code>

  6. <code>}/<code>


  7. <code>}/<code>

這樣的話,gradle 會自動幫你創建這個文件,開發者需要的只是調用 <code>getOutputFile/<code>拿到<code>File/<code>然後寫入即可。

Task 的聯動

我們知道了 Task 產生一個文件的完整流程,我們該如何使用這個文件呢?我們在另外一個 Task 中,定義一下 input

  1. <code>task.input = variantScope.getArtifacts.getArtifactFiles(type); //這裡的 type 和上面的type一樣,比如 InternalArtifactType.BUNDLE/<code>

這個拿到是一個 BuildableArtifact 對象,它的聲明如下:

  1. <code>interfaceBuildableArtifact : Iterable, Buildable, Supplier {/<code>

  2. <code>val files : Set/<code>

  3. <code>fun isEmpty : Boolean/<code>

  4. <code>}/<code>

可以使用 <code>get/<code>獲取一個<code>FileCollection/<code>,當再次調用<code>FileCollection.getFiles/<code>方法時,gradle 就會檢查產生這個產物的 Task 是否已經執行,如果沒有執行,就會先執行前面一個 Task


分享到:


相關文章: