天天看點

Android Studio Assistant 基礎功能 —— ActionⅠ 起源 —— ActionⅡ 操作 Gradle 檔案Ⅲ 狀态管理

Android Studio Assistant 基礎功能 —— ActionⅠ 起源 —— ActionⅡ 操作 Gradle 檔案Ⅲ 狀态管理

小 M 自從上次釋出了

新版 IDEA 插件

之後,Assistant 新穎的接入方式收到了一緻好評,但是第一版的 Assistant 隻有介紹和基礎接入功能,老闆希望小M多加一些功能,比如像 Firebase 接入的時候,有按鈕顯示接入狀态,可以 apply 一些 Gradle 的插件等等功能。

Ⅰ 起源 —— Action

這些肯定難不倒小 M,我們隻要參考下 Firebase 的內建就好了。其實我們大部分業務開發都是基于“事件”這個模型的,包括普通的 Web 後端和前端上的開發,IDEA 相關的内容也不例外,IDEA 響應的使用者的動作一般都是 Action,比如點選菜單裡的某一項,就是響應 AnAction 的操作。比如我們舉個例子,在之前 Assistant 相關的 xml 中,有如下代碼:

<action key="mpaas.integrate_dependencies" label="點選添加">
  ....
</action>           

我們需要對這個 Action 做處理,根據之前 firebase 相關的內建方式,首先需要在 plugin.xml 中注冊如下内容:

<extensions defaultExtensionNs="com.android.tools.idea.assistant">
  <actionHandler implementation="com.alipay.mpaas.assistant.actions.MPIntegrateBaselineActionHandler" />    
</extensions>           

在這個類中,複寫

getId()

方法:

class MPIntegrateBaselineActionHandler: AssistActionHandler {
​
  companion object {
    const val ACTION_KEY = "mpaas.integrate_dependencies"
  }
​
  override fun getId() = ACTION_KEY
}           

這樣就和上面 xml 中的内容對應上了,它提供了一個 handlAction 方法,我們可以在這裡寫邏輯:

override fun handleAction(actionData: ActionData, project: Project) {
    ....
  }           

那這裡就是小助手和我們代碼連接配接的地方了,經過以上的說明,對于響應事件這件事,我們就已經做完了。

Ⅱ 操作 Gradle 檔案

第二步,就是操作 Gradle 檔案了。IDEA 插件裡面其實沒有内置 Gradle 引擎(顯然也不合算),但是它通過 Psi 提供了對 Gradle DSL 解析的弱支援(不是完整支援)。同時提供了一些語義化的模型來簡化這個問題。

我們注意到 Android Studio 提供了這麼一個類 GradleBuildModel 在 Anroid Studio 3.6 中,它提供的接口如下:

Android Studio Assistant 基礎功能 —— ActionⅠ 起源 —— ActionⅡ 操作 Gradle 檔案Ⅲ 狀态管理

看 android / buildscript / dependencies / ext 我們馬上可以知道,這裡對應我們 build.gradle 中幾個 DSL 的 block,比如我們需要往 buildscript 中加入特定的 maven,用來拉取 sdk 或者 gradle 插件的話,那麼按如下方式操作:

① 擷取與修改 GradleBuildModel

GradleModelProvider.get().getBuildModel(project)
    //or
GradleModelProvider.get().getBuildModel(module)           

GradleBuildModel 一般是在 sync 完成之後,會被 AS 緩存起來,我們能以 O(1) 的效率去擷取,然後我們這邊還是以 buildscript 為例,它對應 BuildScriptModel,在 build.gradle 中的内容如下:

buildscript {
    ext.mpaas_artifact = "mpaas-baseline"
    ext.mpaas_baseline = "10.1.68-5"
    repositories {
        mavenCentral()
        jcenter()
        google()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.6.3'
    }
}           

那麼我們往

repositories

添加一個阿裡雲的 maven 倉庫的方式就很簡單了,我們調用

RepositoriesModel

addMavenRepositoryByUrl

方法。

repositoriesModel.addMavenRepositoryByUrl("https://maven.aliyun.com/repository/central")           

② 回寫 GradleBuildModel

這一步改完後,在 BuildModel 就暫存了剛剛的内容,我們還需要把這塊内容回寫回去:

WriteCommandAction.runWriteCommandAction(project, buildModel::applyChanges)           

最終實作效果如下:

Android Studio Assistant 基礎功能 —— ActionⅠ 起源 —— ActionⅡ 操作 Gradle 檔案Ⅲ 狀态管理

③ 添加複雜 Maven DSL 表達式

當然,上面視訊裡面展示的效果是添加一個比較複雜的 maven 配置,有 name / credential 等配置,因為 RepositoriesModel 隻給我們提供了添加 url 一種方式,如果想實作以上的效果,我們需要使用反射的方式,操作 GradleDslBlockModel 的方式來進行。

val myDslElementField = GradleDslBlockModel::class.java.getDeclaredField("myDslElement")
myDslElementField.isAccessible = true

val myDslElement: GradlePropertiesDslElement = myDslElementField.get(repositoryModel) as GradlePropertiesDslElement

val nameElement = GradleNameElement.create("maven")
val mavenDslElement = MavenRepositoryDslElement(myDslElement, nameElement)
val mavenCredentialsDslElement = MavenCredentialsDslElement(mavenDslElement)

mavenCredentialsDslElement.setNewLiteral("username", "xxx")
mavenCredentialsDslElement.setNewLiteral("password", "xxx")

mavenDslElement.setNewLiteral("url", ALIPAY_MAVEN_URL)
mavenDslElement.setNewLiteral("name", "alipay")

mavenDslElement.addParsedElement(mavenCredentialsDslElement)
myDslElement.setNewElement(mavenDslElement)           

完成以上的工作,我們就能通過 Action 的方式操作 Gradle 檔案了。

Ⅲ 狀态管理

點完這個按鈕後,如果能有一個提示來告訴使用者是否接入成功,這簡直就太好啦:

Android Studio Assistant 基礎功能 —— ActionⅠ 起源 —— ActionⅡ 操作 Gradle 檔案Ⅲ 狀态管理

這需要一個叫 ActionStateManager 的元件

<extensions defaultExtensionNs="com.android.tools.idea.assistant">
  <actionStateManager implementation="com.alipay.mpaas.assistant.actions.MPIntegrateBaselineStateManager" />
</extensions>           

我們同時也來寫一個這樣的元件,它繼承于 AssistActionStateManager 裡面有幾個類需要複寫

Android Studio Assistant 基礎功能 —— ActionⅠ 起源 —— ActionⅡ 操作 Gradle 檔案Ⅲ 狀态管理

這裡的 getId() 傳回你剛剛注冊 Action 的那個 id 即可,我這裡就是 mpaas.integrate_dependencies 這裡我們 getState() 支援傳回的狀态有這麼幾種可以選:

Android Studio Assistant 基礎功能 —— ActionⅠ 起源 —— ActionⅡ 操作 Gradle 檔案Ⅲ 狀态管理

當然,你也可以根據提示自己建立一種狀态,按照這個枚舉的名字,和裡面參數的定義,我們能知道每一種狀态代表的含義。

因為這個類的生命周期沒有相關的回調,如果我們需要這個類的執行個體,是以我們需要在 AS 調用 init 方法的時候,自己拿到它的執行個體存起來。

Android Studio Assistant 基礎功能 —— ActionⅠ 起源 —— ActionⅡ 操作 Gradle 檔案Ⅲ 狀态管理

介紹一位不太熟的老友:Android Studio Assistant

Android Studio Assistant 基礎功能 —— ActionⅠ 起源 —— ActionⅡ 操作 Gradle 檔案Ⅲ 狀态管理
Android Studio Assistant 基礎功能 —— ActionⅠ 起源 —— ActionⅡ 操作 Gradle 檔案Ⅲ 狀态管理
Android Studio Assistant 基礎功能 —— ActionⅠ 起源 —— ActionⅡ 操作 Gradle 檔案Ⅲ 狀态管理

繼續閱讀