這是一個新文集,專門用於記錄學習 Kotlin 時遇到的一些問題或者心得體會。由於個人水平有限,文章難免會有錯誤之處,望大佬不吝指教。
Kotlin 由來已久,在17年被谷歌納爲了 Android 開發的一級語言,相必大家也多少有些許瞭解。在開發工作中,還沒能正式的將項目來使用 Kotlin 開發,但是瞭解 Kotlin 顯然已是迫在眉睫了。
舊項目引入 Kotlin 開發
如果你原來的項目使用 Java 編寫的,可以完全放心,我們可以從現在開始每一個新文件都使用 Kotlin 來編寫,Kotlin 與 Java 是百分百的可互相操作的。我們完全可以在保持原項目結構不便的情況下,來使用 Kotlin 進行後續的開發。
1 引入 Kotlin
- 在項目級 build.gradle 文件中引入
buildscript {
ext.kotlin_version = '1.2.41'
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
- 在模塊級 build.gradle 文件中引入
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
- 同步項目,開始使用 Kotlin 開始開發
此時你新建一個 Activity 的話,AS 將提示你可以選擇使用 Kotlin 來進行開發;
2 開始開發
打開我們剛剛新建的這個 Activity,我們來看看 Kotlin 新建的頁面與 Java 文件有那些區別;
class TestActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test)
}
}
在 Kotlin 中申明類也是使用關鍵字 “class”,類之間的繼承使用 “:” ,注意如果被繼承的父類也是一個 Kotlin 類文件(.kt),那麼這個父類必須要使用 open 關鍵字修飾。在 Kotlin 中類默認狀況相當於在 Java 中使用 final 修飾。
另外 Kotlin 支持 override 父類的成員變量,在父類中使用 open 關鍵字修飾的成員變量,在子類中可以使用 override 來重寫,這一點在 Java 中是不支持的。
由於我們在前面引入了 apply plugin: 'kotlin-android-extensions'
,這使得我們可以直接在 Activity 中使用控件的 id 來調用控件,而無需在採用聲明 - findViewById這種方式來實例化空間了。
例如我們在 xml 文件中放一個 TextView 控件:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/mTvText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="這是一個測試的文字"
android:textColor="#ff00ff"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
我們可以這樣在 Activity 中操作:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test)
var oldText = mTvText.text
var newText = "這是一個新的字符串"
mTvText.text=newText
}
上述代碼中,我們可以把 text 直接看成是 TextView 的一個公開的成員變量來使用,省去了 get/set 方法,這樣的例子在 Kotlin 中還有很多。
在 Kotlin 中,我們使用 var 來聲明一個可以讀寫的變量,使用 val 來聲明一個只讀變量。使用 val 聲明的變量,在初始化其值後不允許再次賦值。與 Java 不同的是,在 Kotlin 中申明一個變量不一定需要顯示聲明,Kotlin 可以自動的推斷出一個變量的類型,一個變量在類型確定之後不可以修改其類型。
var a: String = "" //顯示聲明 a 爲 String 類型
var b=1 //自動推斷出 b 爲 int
空安全
Kotlin 是默認空安全的,除非在變量在聲明時使用 “?” 來標註該變量可以爲 null,否則所有變量默認都是不可爲 null,這樣可以最大程度的避免空指針異常。
通常我們在 Android 編程時,都會在類中事先聲明大量的變量,這些變量並不是都能在聲明時初始化,往往很多都是在 Activity 的聲明週期裏完成的初始化。
但是在 Kotlin 中 你會發現有這種情況:
面對這種情況有兩種解決方法:
1. 在 init
代碼塊中初始化
2. 使用 lateinit
和 lazy
進行延時初始化
lateinit
用於 var 變量,lazy
用於 val 只讀變量。
空判斷
如果我們已經顯式的聲明瞭一個變量可以爲 null,那麼在對這個變量進行操作時,我們需要對改變了進行空判斷,這一點 Java 中也是一樣的。
顯而易見的,如果是 Java 代碼,運行到此處的時候回報空指針異常,導致程序崩潰。
在Kotlin 中我們有多重方式來進行空判斷:
1. 傳統的 Java 式在條件中顯示檢查 null
fun print(){
var nullString: String? = null
if (nullString != null) {
println(nullString.length)
} else {
println("empty")
}
}
- 使用安全調用 “?.” 操作符
使用該操作符時,如果對象爲 null,則不會調用該對象的方法,並且返回 null,不爲 null 則正常執行
相當於:
if(nullString == null){
return null
}else{
return nullString.lenght
}
- Elvis 貓王操作符 “?:”
當我們有一個可空的引用 r 時,我們可以說“如果 r 非空,我使用它;否則使用某個非空的值 x”,如下(注意:這是 kotlin 特有的操作,相當於 Java 中的三元操作符,但是 Kotlin 更爲強大允許將 if - else 語句塊中最後一句當成返回值返回):
val l: Int = if (b != null) b.length else -1
我們可以將它簡化爲:
val l = b?.length ?: -1
可以看出,變量 b 直到運算的一刻才轉型成字符型,這一操作在 Java 中是不可以的。需要注意的是,如果一個對象被聲明爲可能爲空,那麼除非是採取方法1在條件中判斷 null,否則我們必須採用安全調用的方式。
4.使用 “!!” 運算符
上述的幾種方式都是讓我們如何避免空指針異常,但有時我們需要在代碼裏拋出這個異常,這一操作需求在 Java 裏是不需要的,因爲只要我們沒有做空判斷,代碼執行到此處如果對象爲空,必然會 NPE (NullPointerException)。但是在 Kotlin 裏一個被聲明爲可空的變量是不能直接被調用的(見上文),這時我們就需要 “!!” 操作符,這個操作符可以使編譯器忽略此處的空檢查,當對象爲空時,運行到此處會 NPE。
上述的四種方法就是我們在 Kotlin 中最常用的四種空判斷方式,下面我們來總結一下:
- 當我們需要一個常規的空判斷時,使用方法1;
- 當我們需要在對象爲空時,表達式結果爲空,使用方法2;
- 當我們需要在對象爲空時,返回另一個表達式或者值,使用方法3;
- 當我們需要在對象爲空時能正常的拋出 NPE,使用方法4;
最後給大家看一個在 Kotlin 中才能使用的騷操作: