秒懂Gadle之一步一步教你將Android Gradle腳本從Groovy改成Kotlin

【版權申明】非商業目的註明出處可自由轉載
博文地址:https://blog.csdn.net/ShuSheng0007/article/details/106763989
出自:shusheng007

系列文章:
秒懂Gradle之從完全懵逼到是懂非懂

概述

通過秒懂Gradle之從完全懵逼到是懂非懂 熟悉了gradle,達到了是懂非懂的境地,今天讓我們實戰演練一下,此演練具有實際意義,如果你願意完全可以將其用在實際項目中。

Gradle從5.0就已經支持Kotlin DSL1.0了,說明Gadle從5.0開始已經準備好在生產上使用了,何況現在已經發展到6.5了,時機已經很成熟。

Android Studio 4.0 對應的gradle 插件爲4.0,對應的Gradle爲6.1.1了,所以是時候嘗試一下使用kotlin DSL寫gradle腳本了。

爲什麼要用Kotlin DSL寫gradle腳本

撇開其他方面,就單從提高程序員生產效率方面就有很多優點:

  • 腳本代碼自動補全
  • 跳轉查看源碼
  • 動態顯示註釋
  • 支持重構(Refactoring)

怎麼樣,要是你經歷過groovy那令人蛋疼的體驗,kotlin會讓你爽的起飛,接下來讓我們開始吧。

從Groovy到Kotlin

讓我們使用Android Studio 新建一個Android項目,AS默認會爲我們生成3個gradle腳本文件。

  • settings.gradle (屬於 project)
  • build.gradle (屬於 project)
  • build.gradle (屬於 module)

我們的目的就是轉換這3個文件

第一步: 修改groovy語法到嚴格格式

groovy既支持雙引號""也支持單引號'',而kotlin只支持雙引號,所以首先將所有的單引號改爲雙引號。
例如 include ':app' -> include ":app"

groovy方法調用可以不使用() 但是kotlin方法調用必須使用(),所以將所有方法調用改爲()方式
例如

implementation "androidx.appcompat:appcompat:1.0.2"

改爲

 implementation ("androidx.appcompat:appcompat:1.0.2")

groovy 屬性賦值可以不使用=,但是kotlin屬性賦值需要使用=,所以將所有屬性賦值添加=.
例如

applicationId "com.ss007.gradlewithkotlin"

改爲

applicationId = "com.ss007.gradlewithkotlin"

完成以上幾步,準備工作就完成了。

第二步:修改文件名並轉換

由於gradle支持groovy 與kotlin腳本混編,所以我們沒轉換完一個文件就同步一下,確保沒有錯誤。

  • 轉換setting.gradle文件

    將文件名加上kts後綴爲setting.gradle.kts

    然後將內容修改爲如下所示(其實完成第一步後就不用做修改了,和groovy一毛一樣,)

    include(":app")
    rootProject.name = "GradleWithKotlinDsl"
    
  • 轉換project的build.gradle文件

    將文件名加kts後綴爲build.gradle.kts

    然後將內容修改爲如下所示:

    buildscript {
        var kotlinVersion: String by extra
        kotlinVersion="1.3.72"
        repositories {
            google()
            jcenter()
        }
        dependencies {
            classpath ("com.android.tools.build:gradle:4.0.0")
            classpath ("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
    
            // NOTE: Do not place your application dependencies here; they belong
            // in the individual module build.gradle files
        }
    }
    
    allprojects {
        repositories {
            google()
            jcenter()
        }
    }
    
    tasks.register<Delete>("clean") {
        delete(rootProject.buildDir)
    }
    

這個文件轉換有兩個地方需要注意:

第一:buildscript{} 裏的ext.kotlin_version'改爲 var kotlinVersion: String by extra
關於extension object 這塊,kotlin表現的不如groovy優秀,比較囉嗦。

第二:task 的申明方式變了

  • 轉換module的build.gradle文件

這個是我們的重點要轉換的了,也最爲複雜。首先將文件名加kts後綴爲build.gradle.kts

然後修改內容如下:

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

android {
    compileSdkVersion (29)
    buildToolsVersion ("30.0.0")

    defaultConfig {
        applicationId = "top.ss007.gradlewithkotlindsl"
        minSdkVersion (21)
        targetSdkVersion (29)
        versionCode= 1
        versionName= "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:1.3.72")
    implementation ("androidx.core:core-ktx:1.3.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")
}

有3處需要特殊處理

第一:插件的引入方式從apply plugin 到聲明式

plugins{
	id(xxx)
  ...
}

第二:buildTypes{} 塊裏面獲取buildType的方式有變化。

因爲buildTypes塊裏面的類型爲NamedDomainObjectCollection<BuildType>,其不存在名爲release的方法。而是通過release這個name可獲取到一個BuildType類型的對象。而這個對象裏面有一個方法叫setMinifyEnabled(false),寫成屬性調用方式爲isMinifyEnabled = false

第三:dependencies{} 塊裏面編譯lib 文件夾中jar文件的內容有變化

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

我們看一下fileTree那個方法的簽名

ConfigurableFileTree fileTree(Map<String, ?> args);

可見其需要一個Map的入參

完成以上幾步後同步一下gradle腳本就ok了。

到目前爲止一切都工作正常,但是在實際項目中我們經常使用project下的gradle腳本的一個extension object來統一維護版本號,如下所示:

ext{
	// Android config
    androidBuildToolsVersion = "30.0.0"
    ...
}

但是在kotlin裏面從其他模塊下訪問不到project下的extra,所以需要使用buildSrc的方式

使用buildSrc改進維護性

在根目錄下創建一個buildSrc目錄,當構建時gradle會自動包括此目錄下的文件,在所有gradle文件中都是可以訪問到這裏面的類,我們可以將版本號統一維護在這裏。

其文件結構如下:
在這裏插入圖片描述

Config 文件內容如下

object Config {
    object Android {
        const val buildToolsVersion = "30.0.0"
        const val minSdkVersion = 21
        const val targetSdkVersion = 29
        const val compileSdkVersion = 29
        const val applicationId = "top.ss007.gradlewithkotlindsl"
        const val versionCode = 1
        const val versionName = "1.0"
    }

    object AndroidLib{
        const val appcompatVersion= "1.1.0"
        const val constraintLayoutVersion="1.1.3"
    }
    ...
}

然後就可以在gradle文件中引用裏面的值了,例如:

defaultConfig {
        applicationId = Config.Android.applicationId
        minSdkVersion (Config.Android.minSdkVersion)
        ...
    }
    
dependencies {
    ...
    implementation ("androidx.appcompat:appcompat:${Config.AndroidLib.appcompatVersion}")
    implementation ("androidx.constraintlayout:constraintlayout:${Config.AndroidLib.constraintLayoutVersion}")
} 

總結

總體來說,gradle團隊已經擁抱Kotlin了,教程也是groovy和kotlin共存的,相信kotlin在gradle的使用中會越來越多的,說不定哪天android studio的模板項目就會使用kotlin作爲默認gradle腳本的,畢竟kotlin已經是Android開發的首推語言了。

不知不覺又快晚上12點了,我也該去睡覺了,腦中突然浮現出一種奇妙的想法:多年年以後回看自己的文章是一種什麼樣的感覺?覺得應該拍點視頻了,多年以後回看自己的視頻感覺比文章要有意思的多吧。

如果要深入瞭解,可以參考官網相關部分 Gradle Kotlin DSL Primer

我覺得是到了點贊收藏的時候了,如果你覺得文章還行,建議關注博主。

本文源碼:GradleWithKotlinDsl

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章