赞
踩
现在Gradle也支持Kotlin了,很多人本来就使用Kotlin开发Android,现在用一种语言同时可以把build脚本的工作也做了,可谓一举两得。
DSL即Domain-Specific Language。
Kotlin与Groovy一样是DSL友好的语言,所以很适合用于Gradle脚本编写。
Kotlin版本的Gradle文件后缀会发生变化, ks
即Kotlin Script
的意思:
.gradle > .gradle.kts
接下来我们学习如何将gradle文件改成Kts的写法:
我们以一个既有Gradle项目为例:
将各个gradle
文件后缀名改为gradle.kts
,并用kotlin重写其内容
include(":app")
rootProject.name = "MyApplication"
buildscript { repositories { google() jcenter() } dependencies { classpath("com.android.tools.build:gradle:3.5.3") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.61") } } allprojects { repositories { google() jcenter() } } task<Delete>("clean") { delete(rootProject.buildDir) }
plugins { id("com.android.application") kotlin("android") kotlin("android.extensions") } android { compileSdkVersion(29) buildToolsVersion = "29.0.0" defaultConfig { applicationId = "<ApplicationId>" minSdkVersion(23) targetSdkVersion(29) versionCode = 1 versionName = "0.1.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } buildTypes { getByName("release") { isMinifyEnabled = false proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") } } } dependencies { implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.61") implementation("androidx.appcompat:appcompat:1.1.0") implementation("androidx.core:core-ktx:1.2.0-rc01") implementation("androidx.constraintlayout:constraintlayout:2.0.0-beta2") testImplementation("junit:junit:4.12") androidTestImplementation("androidx.test.ext:junit:1.1.1") androidTestImplementation("androidx.test.espresso:espresso-core:3.2.0") }
sync并等待成功结束
当项目有多个module且都依赖了相同的库时,库的版本升级或者替换等会导致多个gradle.kts
文件同时修改。此时可以通过将依赖库的配置在buildSrc
中集中管理,减少重复修改的次数:
buildSrc/
文件夹,用来存放依赖库的配置。New > Directory > buildSrc
),不需要 Add Module
buildSrc
目录下会生成build
和.gradle
buildSrc/build.gradle.kts
plugins {
`kotlin-dsl`
}
repositories {
jcenter()
}
buildSrc/src/main/kotlin/depende/
,在目录下创建dependencies/Dep.kt
,用对象类定义全局静态常量,在其他gradle.kts
中可以像调用ext
一样调用到这些kt
中的静态常量。object Dep { object Plugin { val android = "com.android.tools.build:gradle:3.5.3" val kotlin = "org.jetbrains.kotlin:kotlin-gradle-plugin:${Kotlin.version}" val safeArgs = "androidx.navigation:navigation-safe-args-gradle-plugin:${AndroidX.Navigation.version}" } object Test { val junit = "junit:junit:4.12" val androidJunit = "androidx.test.ext:junit:1.1.1" val espressoCore = "androidx.test.espresso:espresso-core:3.2.0" } object Kotlin { const val version = "1.3.61" val stdlibJdk = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$version" } object AndroidX { val appCompat = "androidx.appcompat:appcompat:1.1.0" val coreKtx = "androidx.core:core-ktx:1.2.0-rc01" val constraint = "androidx.constraintlayout:constraintlayout:2.0.0-beta2" } }
定义dependencies/Packages.kt
,用来存放Android相关的配置
object Packages { const val id = "<Application Id>" const val debugIdSuffix = ".debug" object SdkVersion { const val target = 29 const val compile = 29 const val min = 21 } object Version { private const val major = 0 private const val minor = 1 private const val build = 0 val code = (major * 100 + minor * 10 + build) val name = "$major.$minor.$build" } }
值得一提的是,受益于JVM文件之间可以互相调用的特性,普通的gradle
文件也可以调用到kt
文件中的Dep
或者Packages
,实际上groovy
和kt
在配置Gradle时是可以共存的,我们这里只介绍在gradle.kts
中的写法,.gradle
中的写法大家可以自己实践,效果是类似的。
gradle.kts
文件中import上述kt
文件import dependencies.Packages import dependencies.Dep android { compileSdkVersion(Packages.SdkVersion.compile) buildToolsVersion = Packages.SdkVersion.compile.toString() defaultConfig { applicationId = Packages.id minSdkVersion(Packages.SdkVersion.min) targetSdkVersion(Packages.SdkVersion.target) versionCode = Packages.Version.code versionName = Packages.Version.name testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } buildTypes { getByName("release") { isMinifyEnabled = false proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") } } } dependencies { implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) implementation(Dep.Kotlin.stdlibJdk) implementation(Dep.AndroidX.appCompat) implementation(Dep.AndroidX.coreKtx) implementation(Dep.AndroidX.constraint) testImplementation(Dep.Test.junit) androidTestImplementation(Dep.Test.androidJunit) androidTestImplementation(Dep.Test.espressoCore) }
同样,修改根目录的gradle.kts
import dependencies.Dep
buildscript {
dependencies {
classpath(Dep.Plugin.android)
classpath(Dep.Plugin.kotlin)
}
}
org.gradle.internal.exceptions.LocationAwareException: Build file '../build.gradle.kts' line: 10
Script compilation errors:
Line 10: classpath(Dep.Plugin.android)
^ Unresolved reference: Dep
Line 11: classpath(Dep.Plugin.kotlin)
^ Unresolved reference: Dep
经过一番摸索,下面两种方式中的任一种修改后,可以成功sync
build.gradle.kts
中引用的静态变量的定义放到src/main/kotlin/
build.gradle.kts
改回build.gradle
原因不清楚,有清楚的大佬欢迎留言指教
推荐大家以后改用kotlin配置gradle,至少会带来以下好处:
Dep
等全局静态变量传递配置,Groovy则要借助Java的成员变量Project#ext
传递配置Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。