Android Gradle 插件 4.0 支持在 Gradle 构建装备中运用 Kotlin 脚本 (KTS),用于代替 Groovy(过去在 Gradle 装备文件中运用的编程言语)。
将来,KTS 会比 Groovy 更适合用于编写 Gradle 脚本,因为选用 Kotlin 编写的代码可读性更高,并且 Kotlin 供给了更好的编译时查看和 IDE 支持
。
尽管与 Groovy 比较,KTS 当时能更好地在 Android Studio 的代码编辑器中集成,但选用 KTS 的构建速度往往比选用 Groovy 慢,因而在搬迁到 KTS 时应考虑构建性能
。
常用术语
KTS:指Kotlin脚本,是Gradle在构建装备文件中运用的一种 Kotlin 言语方式。Kotlin 脚本是可从命令行运行的 Kotlin 代码。
Kotlin DSL:主要是指 Android Gradle 插件 Kotlin DSL,有时也指底层 Gradle Kotlin DSL。
文件命名
- 用 Groovy 编写的 Gradle build 文件运用
.gradle
文件扩展名 - 用 Kotlin 编写的 Gradle build 文件运用
.gradle.kts
文件扩展名
搬迁思路
Groovy 的语法和 Kotlin 的语法尽管相差不小,但在 Gradle DSL 的规划上,还是尽可能保持了统一性,这显然也是为了降低咱们的学习和搬迁本钱。正因为如此,尽管咱们还是要对两门言语的一些语法细节进行批量处理,搬迁进程实际上并不复杂。
处理字符串字面量
主要修正点在于 settings.gradle
以及几个 build.gradle
。
在 Groovy
中,单引号引起来的也是字符串字面量,因而咱们会面临很多这样的写法:
include ':app', ':tdc_core', ':tdc_uicompat', ':tdc_utils'
这在 Kotlin
中是不允许的,因而需求想办法将字符串字面量单引号统一改为双引号,可以运用Android Studio的 大局正则替换
:
- 匹配框输入正则表达式
'(.*?[^\])'
,替换框中填写"$1"
,这里的$1
对应于正则表达式傍边的第一个元组,如果有多个元组,可以用$n
来表明,其中$0
表明匹配到的整个字符 - 过滤文件后缀,咱们只对
*.gradle
文件做替换 - 在文件后缀后边的漏斗傍边挑选 Excepts String literals and Comments,表明咱们只匹配代码部分
- 在输入框后边挑选
.*
,蓝色高亮表明启用正则匹配
查看匹配内容,对匹配过错的部分进行修正,点击 Replace All
,一切单引号会变成双引号:
include ":app", ":tdc_core", ":tdc_uicompat", ":tdc_utils"
给办法调用加上括号
仍以 settings.gradle
为例:
include ":app", ":tdc_core", ":tdc_uicompat", ":tdc_utils"
此处实际是一个办法调用,在 Groovy 中只要没有歧义,就可以把办法调用的括号省掉,这在 Kotlin 中是不行的,因而需求统一做加括号处理,选用 大局正则替换
办法:
- 匹配框输入正则表达式
(\w+) (([^={\s]+)(.*))
,替换框中填写$1($2)
,其他装备与前面替换引号一样
查看匹配内容,对匹配过错的部分进行修正,点击 Replace All
,一切办法调用都加上了括号:
include(":app", ":tdc_core", ":tdc_uicompat", ":tdc_utils")
开端搬迁
搬迁 settings.gradle
首先,将文件名改为 settings.gradle.kts
, 然后 sync
。
经过前面两步操作,settings.gradle
内容已经是合法的 Kotlin 代码了。
搬迁根目录下的 build.gradle
给文件增加 .kts
后缀,sync
之后开端处理报错:
拜访extra扩展
过去咱们都是经过 ext
拜访 project目标
的动态属性(参阅视频:Project属性都是哪里来的?),Groovy的动态特性支持了这一语法,但Kotlin作为一门静态言语是不支持的。因而想要拜访ext,就需求运用extra扩展,或者 getProperties()["ext"]
,所以:
ext.kotlin_version = "1.4.30"
等价于
extra["kotlin_version"] = "1.4.30"
接下来便是对 kotlin_version
的拜访了,需求将它取出来再运用:
val kotlin_version: String by extra
...
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version")
创建任务
参阅 clean
任务的修正办法:
// 办法一(推荐运用)
tasks.register<Delete>("clean") {
delete(rootProject.buildDir)
}
// 办法二
task("clean", Delete::class) {
delete(rootProject.buildDir)
}
在 Groovy 傍边 Delete 类型是作为参数经过 Key-Value 的方式传递的,Kotlin 傍边直接把它作为泛型参数传入,这样规划是十分契合 Kotlin 的规划思想。
maven装备
maven语法比较简单,直接修正为:
repositories {
google()
mavenCentral()
maven("https://jitpack.io/")
maven("http://maven.xxx.com/") {
// 信赖http协议
isAllowInsecureProtocol = true
}
}
搬迁app模块下的 build.gradle
保证顶部 plugins
装备正确,等候IDE创建索引完毕,各个元素就可以拜访了:
语法细节差异,依据代码提示修正即可,完好装备参阅末尾示例。
显现和隐式 buildTypes
在 Kotlin DSL 中,某些buildTypes
(如debug
和release,
)是隐式供给的。可是,其他buildTypes
则有必要手动创建。
在 Groovy 中,你可能有 debug
, release
, staging
:
buildTypes {
debug {
}
release {
}
staging {
}
}
在 KTS 中,仅 debug
和release
是隐式供给的,staging
有必要手动创建:
buildTypes {
getByName("debug") {
}
getByName("release") {
}
create("staging") {
}
}
参阅示例
settings.gradle.kts
include(":app", ":tdc_core", ":tdc_uicompat", ":tdc_utils")
build.gradle.kts
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:7.0.4")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10")
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
mavenCentral()
maven("https://jitpack.io/")
maven("http://maven.xxx.com/") {
// 信赖http协议
isAllowInsecureProtocol = true
}
}
configurations.all {
resolutionStrategy.apply {
cacheChangingModulesFor(0, "seconds")
cacheDynamicVersionsFor(0, "seconds")
}
}
}
tasks.register<Delete>("clean") {
delete(rootProject.buildDir)
}
app/build.gradle.kts
plugins {
id("com.android.application")
kotlin("android")
}
android {
compileSdk = 31
defaultConfig {
applicationId = "com.xx.component"
minSdk = 21
targetSdk = 31
versionCode = 1
versionName = "1.0"
multiDexEnabled = true
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
signingConfigs {
create("keyStore") {
keyAlias = "component"
keyPassword = "123456"
storeFile = file("xx.keystore")
storePassword = "123456"
}
}
buildTypes {
val signConfig = signingConfigs.getByName("keyStore")
getByName("debug") {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
signingConfig = signConfig
}
getByName("release") {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
signingConfig = signConfig
}
create("staging") {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
signingConfig = signConfig
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
viewBinding.isEnabled = true
}
dependencies {
implementation("androidx.core:core-ktx:1.7.0")
implementation("androidx.appcompat:appcompat:1.4.1")
testImplementation("junit:junit:4.+")
androidTestImplementation("androidx.test.ext:junit:1.1.3")
androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0")
}