是时候把构建脚本从 Groovy 迁移至 Kotlin 了

Kotlin scripting 的优势

对于开发者来说,保证整个项目中语言和代码的一致性是很重要的。尤其是对于 Android 开发者来说,使用 Kotlin 语言编写业务代码,同样也希望使用 Kotlin 语言来构建项目。虽然 Kotlin 脚本目前还是 Experimental 的,但是 Gradle Kotlin DSL 已经足够成熟和稳定,可以胜任 Android 的构建管理
除此之外,Kotlin 脚本相对于 Groovy 来说可读性更高,也更利于 IDE 的语法检查、自动补全和跳转。所以迁移至 Kotlin 脚本是一个很好的选择。

基础使用

顶级 settings.gradle.kts

顶级 settings.gradle.kts 用来定义工程级的仓库配置以及用来构建应用的 module

pluginManagement {
    
    
    repositories {
    
    
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}
dependencyResolutionManagement {
    
    
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
    
    
        google()
        mavenCentral()
    }
}

rootProject.name = "My Application"
include(":app")

pluginManagement() 用来配置各种 Gradle 插件的配置,包括插件所属仓库、依赖处理策略、依赖版本等
dependencyResolutionManagement() 用来配置 Project 以及各个子 module 共用的仓库和依赖(module 独有的依赖最好在 module 自己的 build.gradle.kts 中配置)

顶级 build.gradle.kts

顶级 build.gradle.kts 用来定义 Project 以及各个子 module 共用的插件和属性

plugins {
    
    
    id("com.android.application") version "8.2.0-alpha02" apply false
    id("org.jetbrains.kotlin.android") version "1.8.10" apply false
}

尽管可以使用如下的方法定义 module 共用的属性,但是为了解耦,尽量不要这样用

ext {
    
    
    extra["sdkVersion"] = 33
    extra["appcompatVersion"] = "1.6.1"
}
// compileSdk = rootProject.extra["sdkVersion"]

module 级 build.gradle.kts

module 级 build.gradle.kts 用来配置 module 自己的依赖和配置信息

plugins {
    
    
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
}

android {
    
    
    namespace = "com.yourapp.myapplication"
    compileSdk = 33

    defaultConfig {
    
    
        applicationId = "com.yourapp.myapplication"
        minSdk = 24
        targetSdk = 33
        versionCode = 1
        versionName = "1.0"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        vectorDrawables {
    
    
            useSupportLibrary = true
        }
    }

    buildTypes {
    
    
        release {
    
    
            isMinifyEnabled = false
            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
        }
    }
    compileOptions {
    
    
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    kotlinOptions {
    
    
        jvmTarget = "1.8"
    }
    buildFeatures {
    
    
        compose = true
    }
    composeOptions {
    
    
        kotlinCompilerExtensionVersion = "1.4.3"
    }
    packaging {
    
    
        resources {
    
    
            excludes += "/META-INF/{AL2.0,LGPL2.1}"
        }
    }
}

dependencies {
    
    
    implementation("androidx.core:core-ktx:1.9.0")
}

Groovy 迁移

补充赋值的 =,如 compileSdkVersion 30 变为 compileSdk = 33
调整字符串语法,如 "$project.rootDir/tools/proguard-rules-debug.pro" 变为 "${project.rootDir}/tools/proguard-rules-debug.pro"
val/var 替换 def 进行变量声明,如 def building64Bit = false 变为 val building64Bit = false
调整 list 和 map 语法,如 jvmOptions += ["-Xms4000m", "-Xmx4000m"] 变为 jvmOptions += listOf("-Xms4000m", "-Xmx4000m")

最佳实践

上面我们已经提到,在顶级 build.gradle.kts 中定义 module/subproject 共用的属性不利于解耦,那各个 module 怎么优雅地添加中央化的 dependency 和 version 呢?
一种比较好的方式是使用 Gradle version catalog,使用方式就像直接使用目录层级引用一样,如:

implementation(libs.accompanist.systemuicontroller)
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.appcompat)
implementation(libs.androidx.core.ktx)

前提是需要在根目录下的 gradle 目录下创建一个 libs.versions.toml 文件,它使用 TOML(一种简洁高效的配置文件格式)格式来书写,在这里咱们可以用来声明 [versions], [libraries], [bundles], [plugins],如:

[versions]
accompanist = "0.28.0"
androidGradlePlugin = "8.0.0"
androidxActivity = "1.7.0"

[libraries]
accompanist-systemuicontroller = {
    
     group = "com.google.accompanist", name = "accompanist-systemuicontroller", version.ref = "accompanist" }
androidx-activity-compose = {
    
     group = "androidx.activity", name = "activity-compose", version.ref = "androidxActivity" }

[plugins]
android-application = {
    
     id = "com.android.application", version.ref = "androidGradlePlugin" }
android-library = {
    
     id = "com.android.library", version.ref = "androidGradlePlugin" }

依赖可以用多种形式来声明,"com.mycompany:mylib:1.4", { module = "com.mycompany:other", version = "1.4" } 或者 { group = "com.mycompany", name = "alternate", version = "1.4" } 都可以
如果你不想用默认的 libs 目录名,可以这样来自定义名字:

dependencyResolutionManagement {
    
    
    defaultLibrariesExtensionName.set("projectLibs")
}

version catalog 是类型安全的,编译器会自动检查和自动补全。如果在某些场景下不可用,可以尝试使用不安全的 API:

val versionCatalog = extensions.getByType<VersionCatalogsExtension>().named("libs")
dependencies {
    
    
    versionCatalog.findLibrary("accompanist-systemuicontroller").ifPresent {
    
    
        implementation(it)
    }
}

如果想要在多个团队或者多个项目中共享一个 version catalog 文件,可以这样依赖本地文件:

dependencyResolutionManagement {
    
    
    versionCatalogs {
    
    
        create("libs") {
    
    
            from(files("../gradle/libs.versions.toml"))
        }
    }
}

或者更灵活一点,把 version catalog 以插件的形式使用:

plugins {
    
    
    `version-catalog`
    `maven-publish`
}

catalog {
    
    
    versionCatalog {
    
    
        library("my-lib", "com.mycompany:mylib:1.2")
    }
}

publishing {
    
    
    publications {
    
    
        create<MavenPublication>("maven") {
    
    
            from(components["versionCatalog"])
        }
    }
}

dependencyResolutionManagement {
    
    
    versionCatalogs {
    
    
        create("libs") {
    
    
            from("com.mycompany:catalog:1.0")
            version("accompanist", "0.28.0")
        }
    }
}

总之,我们最终期望的,都是一个类型安全的、中央化的、灵活解耦的依赖和版本管理,使用 Kotlin + version catalog 目前来说是一个比较好的方案

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
在这里插入图片描述
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

全套视频资料:

一、面试合集

在这里插入图片描述
二、源码解析合集
在这里插入图片描述

三、开源框架合集
在这里插入图片描述
欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓

猜你喜欢

转载自blog.csdn.net/weixin_43440181/article/details/130646611