Gradle 3.0.0 插件可以為大型多模塊項目帶來顯著的性能提升,因此,插件的行為,DSL 和 API 都有一些比較大的變化,所以它對于 Android 是一項重大的升級
升級 Gradle 版本
Android 插件 3.0.0 要求 Gradle 4.1+,如果你使用 Android Studio 3.0(以下簡稱 AS )或者更高版本打開已有項目,請按相關提示,將現有項目更新為兼容版本的 Gradle
如果想手動修改 Gradle 版本,修改 gradle-wrapper.properties 內的 URL 地址如下
distributionUrl=\
https\://services.gradle.org/distributions/gradle-4.1-all.zip
使用插件
如果你使用 AS 3.0 或者更高版本打開已有項目,請按相關提示,將現有項目更新為最新版本的 Android 插件,如果要手動升級插件,像下面給出的例子來修改項目根目錄下的 build.gradle 文件
buildscript {
repositories {
...
// 你需要增加下面的倉庫來下載新的插件
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0'
}
}
使用新的依賴配置
Gradle 3.4 引入了新的依賴庫配置,你可以控制這個依賴項具體行為,Android 插件使用了這些新的配置,這可以有效的減少項目的構建時間,下表列出了不同配置的含義以及行為
你的項目有如下依賴關系
App --> moduleA --> moduleB
新的配置項 | 過時的配置項 | 行為 |
---|---|---|
implementation | compile | 如果你的模塊 moduleA 配置了 implementation 的依賴 moduleB,當 moduleB 發生變化時,僅會重新編譯 B 和 A 而不編譯 App,也就是說,implementation 的依賴庫發生了變化,Gradle 只會重新編譯依賴庫和對依賴庫有直接依賴關系的 module ,并且 App 內是調用不到 moduleB 的 api 大多數的 app 應該用這個配置項類配置依賴庫 |
api | compile | 基本等同于 compile ,在 moduleB 發生變化時,會重新編譯整個依賴樹,所以編譯時間相對 implementation 來說更長 |
compileOnly | provided | 等同于 provided ,只是在參與編譯,不會打包到 apk 中(參與編譯的意思是:寫代碼的時候可以直接用,編譯出的 apk 并不包含這個類,像 android.jar 里的類 TextView 等) |
runtimeOnly | apk | 可以理解為與 compileOnly 相反,不參與編譯,但是會輸出到 apk 中,在運行時使用 |
其他類似的有 debugCompile 替換為 debugImplementation 等不再贅述,詳見 Gradle 文檔
在 Google IO 的相關話題中提到了一個建議,就是依賴首先應該設置為 implementation ,如果沒有錯,那就用 implementation ,如果有錯,那么使用 api ,這樣會使編譯速度有所增快
注: compile, provided, 和 apk 現在依然可以使用。但是它們將會在下一個重要更新中移除
使用 annotation processor 依賴指令
在舊版本的插件中,你可以通過 compile 添加一個注解處理器,并且它會正常工作,但是這會向處理器添加大量不必要的依賴關系而對性能產生重大影響
在使用 3.0.0 插件時,你必須使用 annotationProcessor 指令來添加注解處理器在 dependencies 中,像下面給出的一樣
dependencies {
...
annotationProcessor 'com.google.dagger:dagger-compiler:<version-number>'
}
3.0.0 中如果不使用 annotationProcessor 指令添加注解處理器,那么在編譯時將會報錯,如果依賴項包含一些組件需要參與編譯,則使用 compile 再次依賴此依賴項
使用 AAPT2 的行為變化
為了改善增量資源處理,3.0.0 插件默認啟用了 AAPT2 ,盡管 AAPT2 應該能夠立即處理舊的項目,但本節仍將介紹一些您應該注意的行為變更
Android 清單文件的元素層次結構
在舊版本 AAPT,清單文件的元素節點嵌套不正確會被忽略或者打印一個警告
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myname.myapplication">
<application
...
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!-- 錯誤的位置 -->
<action android:name="android.intent.action.CUSTOM" />
</activity>
</application>
</manifest>
舊版本 AAPT 會忽略錯誤的 <action> 標簽,但是在 AAPT2 你將會看到下面的錯誤
AndroidManifest.xml:15: error: unknown element <action> found.
要解決這個問題,請確保你的清單文件的元素嵌套是正確的,可以參考清單文件結構
資源聲明
你將不能再在 name 屬性中指定資源類型,像下面這樣
<style name="foo" parent="bar">
<item name="attr/my_attr">@color/pink</item>
</style>
上面的代碼將會編譯出錯
Error: style attribute 'attr/attr/my_attr (aka my.package:attr/attr/my_attr)' not found.
解決辦法:顯式地指定 type="attr"
<style name="foo" parent="bar">
<item type="attr" name="my_attr">@color/pink</item>
</style>
另外,如果使用 <style> 元素,那么他的 parent 必須也是 style 的資源類型,否則就會報下面的錯誤
Error: (...) invalid resource type 'attr' for parent of style
錯誤的使用 @ 資源引用符號
當你忽略或錯誤地放置資源引用符號 @ 時,AAPT2 現在會觸發構建錯誤,例如
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
...
<!-- 引用資源時缺失 @ 符號 -->
<item name="colorPrimary">color/colorPrimary</item>
</style>
在編譯時,AAPT2 將會報下面的錯誤
ERROR: expected color but got (raw string) color/colorPrimary
此外,請考慮從 android 命名空間訪問資源時是否錯誤地包含該符號,如下所示
<!-- 當從 “android” 命名空間內引用資源時,應省略 @ 符號 -->
<item name="@android:windowEnterAnimation"/>
在編譯時,AAPT2 將會報錯
Error: style attribute '@android:attr/windowEnterAnimation' not found
聲明:本文節選翻譯自Migrate to Android Plugin for Gradle 3.0.0,有部分內容是根據自己的理解來寫的,如有偏差,歡迎指正