Android Studio上Kotlin的入門

saber alter發表於2021-01-03

為什麼選擇Kotlin

在 2019 年 Google I/O 大會上,他們宣佈今後將優先採用 Kotlin 進行 Android 開發。如今,超過 60 款 Google 應用是用 Kotlin 構建的,其中包括 Google 地圖、Google Home、Google Play 和 Google 雲端硬碟等應用。根據 Google 的說法,Google Play 商店前 1000 個應用中有 60% 以上也使用 Kotlin。Kotlin是谷歌在安卓應用上大力支援且推薦的語言,在構建新的 Android 開發工具和內容(例如 Jetpack 庫、示例、文件和培訓內容)時,谷歌會在設計層面上先考慮 Kotlin 使用者。

Kotlin是什麼

Kotlin是由JetBrains公司開發設計的一門解釋性語言,在2011年,JetBrains公佈了Kotlin的第一個版本,並在2012年將其開源。2016年,Kotlin釋出了1.0正式版,JetBrains在自家的旗艦開發工具IntelliJ IDEA中加入了對Kotlin的全面支援,Kotlin在這時期,已經足夠成熟和穩定了。2017年,Android Studio也加入了對Kotlin的支援。

Kotlin的優勢

  1. 程式碼更少、可讀性更強 可以讓我們寫更少的程式碼,以及花費更少的時間來理解別人的程式碼;
  2. 更安全的程式碼 Kotlin 有許多語言功能,可幫助我們避免 null 指標異常等常見程式設計錯誤;
  3. 與 Java 的互操作性 可以在 Kotlin 程式碼中呼叫 Java 程式碼,或者在 Java 程式碼中呼叫 Kotlin 程式碼。對於原有的java專案,在應用程式中可以將 Kotlin 與 Java 程式語言一起使用, 而無需將所有程式碼遷移到 Kotlin;
  4. Android Jetpack 與其他庫中的 Kotlin 支援 KTX 擴充套件 為現有的 Android 庫新增了 Kotlin 語言特性,如協程、擴充套件函式、lambdas 與命名引數;
    5.易學易用 Kotlin 非常易於學習,尤其是對於 Java 開發人員而言。

第一個Kotlin應用

知道了Kotlin是什麼,那我們就先用Android Studio來建立你的第一個Kotlin應用吧

建立Kotlin應用很簡單,所有的步驟都和建立Java應用是一樣的,只需在建立時,將所使用的語言改為Kotlin就行
建立Kotlin專案
創好了後,我們開啟MainActivity,可以看到,比起java,Kotlin的程式碼要少一些,寫類和方法的語法規則也不同。

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

Kotlin的基本語法規則

Kotlin每一行程式碼的結尾是不用加分號的

變數

在Kotlin中定義變數的方式和java區別很大,Kotlin定義變數時,只允許在變數前宣告兩種關鍵詞:val 和 var

val(value的縮寫),它用來宣告一個不可變的變數。這種變數在初始初始賦值之後,就不能再被複制了,相當於java中用 final宣告。
var(variable的縮寫),它用來宣告一個可變的變數。這種變數在初始賦值之後依舊可以重新賦值。

常量與變數都可以沒有初始化值,但是在引用前必須初始化

編譯器支援自動型別判斷,即宣告時可以不指定型別,由編譯器判斷。

val x: Int = 10 //完整的宣告變數
val y = 10 // 不指定變數型別,系統自動推斷變數型別為Int
val z: Int // 如果不在宣告時初始化值,則必須提供變數型別
z = 10 //對不可變的變數明確賦值,賦值後不能再次賦值

var a = 1 // 系統自動推斷變數型別為Int
a += 1 // 變數可修改

讀者可以看到,Kotlin中Int的首字母是大寫的,而Java中int的首字母是小寫的。這是因為Kotlin沒有使用Java的基本資料型別,而是使用了物件資料型別。在java中,int是關鍵字,而在Kotlin中,Int是一個,它有自己的方法和資料結構。所以,我們可以給Int等物件資料型別新增擴充套件函式,文章後文的Toast簡化就是基於此點的。

函式

Kotlin中定義函式的關鍵字是fun(function的縮寫),無論你想定義什麼函式,都必須用fun進行宣告
緊跟在fun後面的是函式名,函式名後括號裡面放的是接收的引數。引數的格式名是“引數名:引數型別
若是有返回值的話,就將返回值型別以冒號隔開,寫在函式名括號的後面;若是沒有返回值,可以省略不寫,或者寫關鍵字為 Unit,類似與java的void

例項:接收兩個不同型別引數,且返回值為String的函式

fun functionDemo(parm1 : Int, parm2 :  String) : String{
     return parm2
}

例項:當一個函式中只有一行程式碼時,Kotlin允許我們不必編寫函式體,可以直接將唯一的一行程式碼用等號連線,直接寫在函式定義的後面

//改寫前
fun sum(parm1: Int, parm2: Int): Int {
    return a + b
}

//改寫後
fun sum(parm1: Int, parm2: Int) = a + b    //返回值類似也省略了,由編譯器自動推斷型別

匿名函式

Kotlin支援lambda表示式。並非每個函式都需要一個名稱。某些函式通過輸入和輸出更直接地進行標識。這些函式稱為“匿名函式”。

lambda表示式的寫法為:(type1,type*) -> type_return = { }
使用例項:

fun main(args: Array<String>) {
    val sumLambda: (Int, Int) -> Int = {x,y -> x+y}  //(Int, Int) -> Int = {x,y -> x+y}就是一個匿名函式
    println(sumLambda(1,2))  // 輸出 3
}

字串模板

字串可以包含模板表示式,即可求值的程式碼片段,並將它的結果連線到字串裡面。

字串模板表示式可以是 $變數名 ${變數名}
例項:

val a = 10
val s1 = "a = $a" // 結果為 "a = 10"

val s = "abc"
val str = "$s.length is ${s.length}" // 結果為 "abc.length is 3"

a = 2
// 模板中的任意表示式:
val s2 = "${s1.replace("is", "was")}, but now is $a" 
//結果為“a was 10 , but now is 2 ”

var name = "張三"
var sex = true
var date = "2021年1月2日"
var time = "11點59分"
var work ="該睡覺了"
val orderInfo = "你好,${name} ${if(sex)"cool boy" else "cool girl" },"+"現在已經是${date}\t${time}了,"+"你${cacke}"
//結果為"你好,張三 cool boy,現在已經是2021年1月2日 11點59分了,你該睡覺了"

註釋

Kotlin 支援單行(或行末)與多行(塊)註釋。

// 這是一個行註釋
/* 這是一個多行的
塊註釋。 */

Kotlin 中的塊註釋可以巢狀

/* 註釋從這裡開始
/* 這是巢狀的註釋 */
並且在這裡結束。 */

Null 安全

在某些語言中,可以宣告引用型別變數而不明確提供初始值。在這類情況下,變數通常包含 null 值。預設情況下,Kotlin 變數不能持有 null 值。這意味著以下程式碼段無效:

// 賦值失敗
val languageName: String = null

要使變數持有 null 值,它必須是可為 null 型別。可以在變數型別後面加上 ? 字尾,將變數指定為可為 null,如以下示例所示:

val languageName: String? = null

當使用可以可返回Null的函式時,要注意Null安全,應該先做判斷處理

fun printProduct(arg1: String, arg2: String) {
    val x = parseInt(arg1)
    val y = parseInt(arg2)

    // 直接使用 "x * y" 會導致編譯錯誤,因為它們可能為 null
    if (x != null && y != null) {
        // 在Null檢測之後,x 與 y 會自動轉換為非空值(non-nullable)
        println(x * y)
    }
    else {
        println("'$arg1' or '$arg2' is not a number")
    }    
}

型別檢測和自動型別轉換

我們可以使用 is運算子檢測一個表示式是否某型別的一個例項(類似於Java中的instanceof關鍵字)。 如果一個不可變的區域性變數或屬性已經判斷出為某型別,那麼檢測後的分支中可以直接當作該型別使用,無需顯式轉換
示例:

//寫法一
fun getStringLength(parm: Any): Int? {
  if (parm is String) {
    // 做過型別判斷以後,"parm"會被系統自動轉換為String型別
    return parm.length 
  }

  // 這裡的parm仍然是Any型別的引用
  return 0
}

//寫法二
fun getStringLength(parm: Any): Int? {
    if (parm !is String) return 0

    // "parm" 在這一分支自動轉換為 "String"
    return parm.length
}

//寫法三
fun getStringLength(parm: Any): Int? {
  //用到了&&運算子的短路特性 
  // 在 "&&" 運算子的右側, "parm" 的型別將會被自動轉換為 "String"
  if (parm is String && obj.length > 0)
    return parm.length
  return 0
}

簡化Toast的用法

Toast的標準用法為:

Toast.makeText(content, “this is content by showed”, Toast.LENGTH_SHORT).show()

如果你需要多次呼叫Toast方法,就會感覺這是一段很長,且內容都是重複的程式碼,且容易忘記呼叫最後的show()方法,不僅Toast沒法彈出來,還容易產生一些奇怪的bug。
一般而已,我們呼叫Toast時,想要顯示的都是String或者Int型別的資料,我們只需要在Kotlin中的String和Int類中各新增一個擴充套件函式,然後在裡面封裝彈出toast的具體邏輯就好了。這樣,想要彈出Toast提示的時候,只要呼叫它們的擴充套件函式就可以了。
我們只需要新建一個kt檔案,然後寫如下程式碼就可以了:

fun String.showToast(context:Context,  showTime: Int = Toast.LENGTH_SHORT){
     Toast.makeText(context, this,  showTime).show()
}

fun Int.showToast(context:Context,  showTime: Int = Toast.LENGTH_SHORT){
     Toast.makeText(context, this,  showTime).show()
}

有了這個擴充套件程式碼後,我們再需要使用Toast時,只需要這麼寫就可以了:

“This is want to show”.showToast(context)

在上述函式中, showTime是有預設值的引數,我們也可以重新設定Toast的顯示時間:

“This is want to show more long”.showToast(context, Toast.LENGTH_LONG)

相關文章