使用Kotlin DSL构建Android项目

使用Kotlin DSL构建Android项目

前言

Android支持使用Kotlin DSL来构建Gradle脚本了,还不赶紧学习一波?

本文主题:

1.如何使用Kotlin DSL替换Groovy

2.过程中遇到的问题以及解决方法

为什么要使用Kotlin DSL

使用Kotlin DSL 的优势:

  • 由于现在Kotlin是Android官方推荐语言,因此使用Kotlin构建Gradle脚本有利于整个项目开发语言的统一,不需要另外学习Groovy的语法
  • Kotlin DSL 支持跳转到源码
  • Kotlin DSL 在编译时检查错误
  • Kotlin DSL 支持代码自动补全和语法高亮

Kotlin DSL的劣势:

  • 编译速度比Groovy慢

从Groovy迁移到Kotlin DSL

Gradle 版本: 3.5.3

gradle-wrapper版本:5.6.4

新建一个Android项目

我们以一个新的Android项目为例,一步步从groovy迁移到Kotlin DSL

第一步:修改setting.gradle文件

setting.gradle 重命名为 setting.gradle.kts

所有的Kotlin DSL 文件,都是以.kts 为文件名后缀

然后修改文件里面的内容:

include (":app")

rootProject.buildFileName = "build.gradle.kts"

这里做的事情也很简单,就是把原本的 ":" 改成了 "()" 这也是Kotlin DSL和Groovy语法的差别之一。

第二步:修改Project的build.gradle文件

build.gradle 重命名为 build.gradle.kts

然后修改内容:

buildscript {
    val kotlin_version = "1.3.61" // #1
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath("com.android.tools.build:gradle:4.0.0-beta01")  // #2
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version")

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

tasks.register("clean", Delete::class) {  // #3
    delete(rootProject.buildDir)
}

这里主要修改的就是三点,我已经在代码中标识出来了:

  • ext改成 val,val是Kotlin不可变变量的关键字
  • classpath 的 单引号 改为 双引号
  • task 同样需要改成 Kotlin 的语法

第三步:修改App的build.gradle文件

同样的,首先把build.gradle重命名为 build.gardle.kts

这里需要做的变动就比较多了,直接上修改后的代码:

plugins {  // #1
    id("com.android.application")
    kotlin("android")
    kotlin("android.extensions")
}

android {
    compileSdkVersion(29)  // #2
    buildToolsVersion("29.0.3")

    defaultConfig {
        applicationId = "com.bluelzy.kotlindsldemo"
        minSdkVersion(21)
        targetSdkVersion(29)
        versionCode = 1
        versionName = "1.0"
    }

    buildTypes {
        getByName("release") {   // #3
            isMinifyEnabled = false
            proguardFiles (getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
        }
    }
}

dependencies {
    implementation(
        fileTree(  // #4
            mapOf(
                "dir" to "libs", "include" to listOf("*.jar")

            )
        )
    )
    implementation (kotlin(
        "stdlib-jdk7",
        org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION
    ))
    implementation("androidx.core:core-ktx:1.2.0")
    implementation("androidx.appcompat:appcompat:1.1.0")
    implementation("androidx.constraintlayout:constraintlayout:1.1.3")
    testImplementation("junit:junit:4.12")
    androidTestImplementation("androidx.test.ext:junit:1.1.1")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.2.0")

}

需要注意的地方同样在注释中标识出来了:

  • apply 需要改成 plugins
  • 原本 : 的写法统统换成 () 或者 =,这是kotlin的setter语法
  • 注意buildTypes和fileTree的变化

完成了这几步之后,我们就可以点击sync project,如无意外的话应该是可以成功的,到目前为止其实我们就已经从Groovy成功迁移到了Kotlin DSL了。但是大家有没有发现一个问题,就是现在我们所有的版本号,依赖版本,TargetSDK等等,都是直接写在build.gradle.kts文件中的,能不能把这些变量都统一放到一个地方管理呢?特别是多个Module的时候,我们希望只要改动一个地方,所有的依赖都能够同步。

其实官方已经给我们提供了一个解决方案了,那就是使用buildSrc

第四步:创建buildSrc文件夹

在根目录下创建一个buildSrc文件夹,也就是和app文件夹同一等级。创建后的结果应该是这样的:

大家可以先忽略Kotlin文件夹里面的3个文件。只要创建了src/main/kotlin 以及 build.gradle.kts 文件就可以了。

接下来就要修改build.gradle.kts文件了:

plugins {
    `kotlin-dsl`
}

repositories {
    jcenter()
}

解释一下,这一个buildSrc文件夹的作用是什么呢?

官方推荐我们使用这个文件夹来管理整个项目的依赖,也就是说,我们可以在这个路劲定义多个和依赖相关的类。

创建Dependencies.kt文件

object Apps {
    const val compileSdk = 29
    const val minSdk = 21
    const val targetSdk = 29
    const val versionCode = 1
    const val versionName = "1.0.0"
}

object Versions {
    const val gradle = "3.5.3"
    const val kotlin = "1.3.61"
    const val appcompat = "1.0.2"

    /* test */
    const val junit = "4.12"
}

object Libs {
    const val kotlin = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${Versions.kotlin}"
    const val appcompat = "androidx.appcompat:appcompat:${Versions.appcompat}"
}

object TestLibs {
    const val junit = "junit:junit:${Versions.junit}"
}

举个例子,我们在这个kt文件中定义了三个单例,分别用于存放App相关的版本号,依赖相关的版本号,以及依赖包的名称

然后我们就可以在App的build.gradle.kts里面用上这些定义的常量了

更新后的build.gradle.kts:

// 省略代码
android {
    compileSdkVersion(Apps.compileSdk)

    defaultConfig {
        applicationId = "com.bluelzy.kotlindsldemo"
        minSdkVersion(Apps.minSdk)
        targetSdkVersion(Apps.targetSdk)
        versionCode = Apps.versionCode
        versionName = Apps.versionName
    }
    // 省略代码
}

dependencies {

    // android supports
    implementation(Libs.appcompat)

    // test
    testImplementation(TestLibs.junit)
}

上面的文件并不是完整的,大家可以自己按照项目里的依赖添加到Dependencies.kt文件,以及更新build.gradle.kts文件即可。

如果项目有多个Modlue,而且依赖关系也很复杂,那么我们可以在buildSrc/src/main/kotlin 目录下多定义几个kt文件,用于管理不同的依赖。这里就不展开了。

总结

其实使用Kotlin DSL来替代Groovy的步骤比较简单,就是把3个gradle相关的文件重命名为.kts,然后用Kotlin的语法修改,最后在buildSrc目录下创建依赖相关的kt文件。

但是在这个过程中同样会遇到一些问题,以我个人遇到的问题为例

1.项目能build成功,也可以正常运行,但是在App的build.gradle.kts文件中 android 标签和 implementation 一直报错,重启AS,clean project,还有清除缓存都无法解决问题。

如果出现这个问题的话,大家可以尝试修改gradle的版本,我一开始创建的项目使用的gradle版本是:

gradle: 4.0.0-beta01
gradle-wrapper: https\://services.gradle.org/distributions/gradle-6.1.1-all.zip

可能是新版本的Bug,死活都找不到android
后面我就把gradle降级为:

Gradle 版本: 3.5.3

gradle-wrapper版本:5.6.4

然后就可以了

2.在修改build.gradle.kts文件的过程中会报错,这个时候大家可以打开Gradle面板,找到里面的build setup选项,运行init

最后附上一张使用了Kotlin DSL的build.gradle.kts文件截图,是不是比之前清晰多了呢?

参考

本文以创作共用版权协议发布,转载本文要求遵循“署名-非商业性使用-相同方式共享3.0”的创作共用协议,并以链接形式指明本文地址。

本文链接地址: https://www.bluelzy.top/kotlin_dsl_for_android/

发表评论

电子邮件地址不会被公开。 必填项已用*标注