小伙快把你的Android从Groovy迁移到DSL

小伙快把你的Android从Groovy迁移到DSL

Kotlin 脚本 (KTS) 比 Groovy 更适合用于编写 Gradle 脚本,因为采用 Kotlin 编写的代码可读性更高,并且 Kotlin 提供了更好的编译时检查和 IDE 支持。Android Gradle 插件 4.0 支持在 Gradle build 配置中使用 KTS。

1.概念解释

  • Gradle: 自动化构建工具. 平行产品: Maven.
  • Groovy: 语言, 编译后变为JVM byte code, 兼容Java平台.
  • DSL: Domain Specific Language, 领域特定语言.
  • Groovy DSL: Gradle的API是Java的,Groovy DSL是在其之上的脚本语言. Groovy DS脚本文件后缀: .gradle.
  • KTS:是指 Kotlin 脚本,这是 Gradle 在构建配置文件中使用的一种 Kotlin 语言形式。Kotlin 脚本是可从命令行运行的 Kotlin 代码。
  • Kotlin DSL:主要是指 Android Gradle 插件 Kotlin DSL,有时也指底层 Gradle Kotlin DSL

在讨论从 Groovy 迁移时,术语“KTS”和“Kotlin DSL”可以互换使用。换句话说,“将 Android 项目从 Groovy 转换为 KTS”与“将 Android 项目从 Groovy 转换为 Kotlin DSL”实际上是一个意思。

2.Groovy和KTS对比

类型KotlinGroovy
自动代码补全支持不支持
是否类型安全不是
源码导航支持不支持
重构自动关联手动修改

3.优点:

  • 可以使用Kotlin, 开发者可能对这个语言更熟悉更喜欢.
  • IDE支持更好, 自动补全提示, 重构,imports等.
  • 类型安全: Kotlin是静态类型.
  • 不用一次性迁移完: 两种语言的脚本可以共存, 也可以互相调用.

4.缺点和已知问题:

  • 目前,采用 KTS 的构建速度可能比采用 Groovy 慢。
  • Project Structure 编辑器不会展开在 buildSrc 文件夹中定义的用于库名称或版本的常量。
  • KTS 文件目前在项目视图中不提供文本提示

5.脚本文件命名

脚本文件扩展名取决于编写 build 文件所用的语言:

  • 用 Groovy 编写的 Gradle build 文件使用 .gradle 文件扩展名。
  • 用 Kotlin 编写的 Gradle build 文件使用 .gradle.kts 文件扩展名。

6.转换语法差异:

Groovy 和 Kotlin 的语法之间存在一些普遍差异,因此您需要在 build 脚本中应用以下更改。

为方法调用添加圆括号

提示:首先,在更改文件扩展名之前,最好先在 Groovy 代码中添加圆括号。这样可以更轻松地转换为 Kotlin。

Groovy 允许您在方法调用中省略圆括号,而 Kotlin 则要求使用圆括号。如需迁移配置,请为这些类型的方法调用添加圆括号。以下代码展示了如何在 Groovy 中配置设置:

compileSdkVersion 30

以下是使用 Kotlin 编写的相同代码:

compileSdkVersion(30)

在这里插入图片描述

7.转换字符串

以下是 Groovy 和 Kotlin 在字符串方面的差异:

  • 用于定义字符串的双引号:虽然 Groovy 允许使用单引号来定义字符串,但 Kotlin 要求使用双引号。

  • 基于句点表达式的字符串插值:在 Groovy 中,对于句点表达式的字符串插值,您可以仅使用“$”前缀,但 Kotlin 要求您用大括号将句点表达式括起来。

    没转换前的字符串都是单引号:

    proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    
       composeOptions {
            kotlinCompilerExtensionVersion '1.4.2'
        }
        packagingOptions {
            resources {
                excludes += '/META-INF/{AL2.0,LGPL2.1}'
            }
        
    

    不过,转换后,上述代码都是双引号

     proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    
    composeOptions {
            kotlinCompilerExtensionVersion = ("1.2.0")
        }
        packagingOptions {
            resources {
                excludes += ("/META-INF/{AL2.0,LGPL2.1}")
            }
        }
        
    

    如需了解详情,请参阅 Kotlin 文档中的字符串模板

在这里插入图片描述

8.重命名文件扩展名

请在迁移每个 build 文件的内容时将 .kts 添加到其文件扩展名后。例如,选择一个 build 文件(如 settings.gradle 文件)。将该文件重命名为 settings.gradle.kts,然后将其内容转换为 KTS。请确保您的项目在迁移每个 build 文件之后仍然可以编译。

请先迁移最小的文件以便积累经验,然后再继续。项目中可以混合使用 KTS 和 Groovy build 文件,因此您无需着急,可以小心细致地进行迁移。

def 替换为 valvar

def 替换为 valvar,这是在 Kotlin 中定义变量的方式。以下是 Groovy 中的变量声明:

9.把app的build.gradle改成build.gradle.kts:

报错信息如下:

在这里插入图片描述

根据官网的规则修改如下:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

10.完整的配置如下:

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

android {
    namespace  = ("com.example.dropdowncomposedemo")
    compileSdk = 33

    defaultConfig {
        applicationId = ("com.example.dropdowncomposedemo")
        minSdk = 23
        targetSdk = 33
        versionCode = 1
        versionName = "1.0"

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

    buildTypes {
        release {
            //minifyEnabled = 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.2.0")
    }
    packagingOptions {
        resources {
            excludes += ("/META-INF/{AL2.0,LGPL2.1}")
        }
    }
}


dependencies {

    implementation("androidx.core:core-ktx:1.7.0")
    implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.3.1")
    implementation("androidx.activity:activity-compose:1.3.1")
    implementation("androidx.compose.ui:ui:1.2.0")
    implementation("androidx.compose.ui:ui-tooling-preview:1.2.0")
    implementation("androidx.compose.material:material:1.2.0")
    testImplementation("junit:junit:4.13.2")
    androidTestImplementation("androidx.test.ext:junit:1.1.5")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
    androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.2.0")
    debugImplementation("androidx.compose.ui:ui-tooling:1.2.0")
    debugImplementation("androidx.compose.ui:ui-test-manifest:1.2.0")
}

11.改完之后验证一下配置:

在这里插入图片描述

12.修改setting.gradle为setting.gradle.kts:

在这里插入图片描述

发现改完后又报错了,根据错误提示修改后的配置如下:
在这里插入图片描述

pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
    }
}
rootProject.name = "DropDownComposeDemo"
include (":app")

13.修改项目的build.gradle为build.gradle.kts:

val compose_ui_version = ("1.2.0")
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        google()
        mavenCentral()
        maven ("https://maven.aliyun.com/nexus/content/repositories/releases/")

    }
    dependencies {
        classpath ("com.android.tools.build:gradle:7.4.1")
        classpath (kotlin("gradle-plugin", version = "1.7.0"))
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

plugins {
    id("com.android.application") version "7.4.1" apply false
    id("com.android.library") version  "7.4.1" apply false
    // 声明kotlin 1.7.30  插件版本 但是并不直接引入
    kotlin("jvm") version "1.7.0" apply false
}

在这里插入图片描述

14.统一管理依赖库:

​ 新建一个build.src目录

在这里插入图片描述

15.添加kotlin-dsl插件:

在这里插入图片描述

16.新建一个名为libs的库管理类:

import java.text.SimpleDateFormat

object libs {
    const val StoreFile = "../"
    const val StorePassword = "123456"
    const val KeyAlias = ""
    const val KeyPassword = "123456"
    const val namespace  = "com.example.dropdowncomposedemo"
    const val applicationId = "com.example.dropdowncomposedem"
    const val compileSdkVersion = 29
    const val buildToolsVersion = "30.0.2"
    const val minAndroidSdk = 21
    const val targetSdk = 29
    const val versionCode = 1
    const val versionName = "1.0.0"

    val dateFormat: String = SimpleDateFormat("HHmm").format(System.currentTimeMillis())

    //libs version
    const val agp_version = "7.4.1"
    const val kotlin_version = "1.7.0"
    const val ksp_verion = "$agp_version-1.0.6"
    const val kotlinx_coroutines_version = "1.3.9"
    const val lifecycle_version = "2.2.0"
    const val room_version = "2.2.6"
    const val work_version = "2.4.0"
    const val retrofit_version = "2.9.0"
    const val moshi_version = "1.11.0"
    const val fragment_version = "1.2.5"
    const val status_bar_util_version = "1.5.1"
    const val glide_version = "4.11.0"
    const val transformations_version = "4.0.0"
    const val core_ktx_version = "1.7.0"
    const val appcompat_version = "1.6.0"
    const val material_version = "1.4.2"
    const val constraintlayout_version = "2.1.4"
    const val espresso_core_version = "3.5.1"
    const val lifecycle_runtime_ktx_version = "2.3.1"
    const val activity_compose_version = "1.3.1"
    const val androidx_compose_ui_version = "1.4.0"
    const val androidx_ui_tooling_preview = "1.4.0"
    const val junit_version = "4.13.2"
    const val androidx_test_junit_version = "1.1.5"
    const val androirx_ui_test_junit4_version = "1.4.0"
    const val android_ui_tooling_version = "1.4.0"
    const val android_ui_test_manifest_version = "1.4.0"

    //android libs
    const val androidx_appcompat = "androidx.appcompat:appcompat:$appcompat_version"
    const val com_google_android_material = "com.google.android.material:material$material_version"
    const val androidx_constraintlayout = "androidx.constraintlayout:constraintlayout$constraintlayout_version"
    const val androidx_espresso_core = "androidx.test.espresso:espresso-core$espresso_core_version"
    const val kotlinx_coroutines_core = "org.jetbrains.kotlinx:kotlinx-coroutines-core$kotlinx_coroutines_version"
    const val core_ktx = "androidx.core:core-ktx:$core_ktx_version"
    const val activity_compose = "androidx.activity:activity-compose:$activity_compose_version"
    const val lifecycle_runtime = "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_runtime_ktx_version"
    const val compose_ui = "androidx.compose.ui:ui:$androidx_compose_ui_version"
    const val ui_tooling_preview = "androidx.compose.ui:ui-tooling-preview:$androidx_ui_tooling_preview"
    const val junit = "junit:junit:$junit_version"
    const val androidx_test_junit = "androidx.test.ext:junit:$androidx_test_junit_version"
    const val androidx_ui_test_junit4 = "androidx.compose.ui:$androirx_ui_test_junit4_version"
    const val ui_tooling = "androidx.compose.ui:ui-tooling:$android_ui_tooling_version"
    const val ui_test_manifest = "androidx.compose.ui:ui-test-manifest:$android_ui_test_manifest_version"
}

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

17.修改新的依赖引入方式:

两种引入方式:

17.1.只修改依赖版本的引入:

在这里插入图片描述

17.2.修改整个依赖库的引入:

在这里插入图片描述

18.运行修改后的配置效果:

在这里插入图片描述
在这里插入图片描述

19.总结:

虽然迁移时遇到很多问题,但是根据官方文档和各种资料还是一步步慢慢解决了,可以说是过程充满曲折和坎坷,刚开始不熟悉配置,统一管理版本时遇到各种问题,最后发现是kotlin、compose和gradle版本不统一,有点粗心导致引入依赖库的名字写错了,一直以为是vpn的问题,可是我打开自己购买的软件重新构建还是失败,最后调试了半天才发现是依赖库引入的名字和官网的对不上,导致一直构建失败,很多库都没下载成功,遇到问题不要慌,慢慢找到原因和解决方法就好,前面道路险且难,需要一直砥砺前行,如果感兴趣的小伙伴可以自己去试试,后面会把项目慢慢尝试转换成dsl语法。

20.项目源码地址:在dev_dsl分支

https://gitee.com/jackning_admin/drop-down-compose-demo

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值