Android谷歌官方語言Kotlin用法入門教程

艾陽丶發表於2017-05-19

導語


    Kotlin語法與Java的區別挺大的,一開始很想放棄,如果不是谷歌讓其成為Android的官方開發語言,想必很少人會嘗試這樣一門小眾語言,但是換了Kotlin後會發現這些年究竟浪費多少時間在寫無用的Java程式碼了,Kotlin在相容Java的基礎上還大大提升效率。Kotlin有許多特性但對於初學者來說,快速適應和學習更為重要!很多時候我們都是在不明白其原因就開始使用的,正如我們不可能把Retrofit、RxJava、OKHttp原理研究透才使用它。目前使用Kotlin的主要原因是因為它語法簡潔,支援lambda表示式,強大的when語法,不用寫分號結尾,光是這些就足以讓我們喜歡上Kotlin。還有些空安全之類的特性,服務端資料型別太多null了。突然一臉懵逼地看著Kotlin火了,Google IO的對開發者的影響真是不容小覷。在此也就把上一篇Kotlin基礎文章的知識也搬遷過來,稍作修改。

建立一個Kotlin專案


首先,得把你的IDE-As保證是:Android Studio 3.0以上新版本。Android Studio 中文社群(官網) -Android App開發工具集

1、勾選:include Kotlin support  點選finish完成。



2、建立好的Activity中便已經是Kotlin的程式碼,看起來與Java程式碼本身非常相似:Kotlin檔案以.kt結尾。

使用Kotlin宣告Activity:

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

使用Kotlin設定點選事件:

val textView = findViewById(R.id.text) as TextView
textView.setOnClickListener {

    Toast.makeText(this,"Hello Kotlin!",Toast.LENGTH_SHORT).show()

}
小結:上面的setContentView以及下面的Toast就是Android提供的API,我們可以直接使用了,並且setOnClickListener方法內部並不需要new OnClickListener物件!直接寫點選實現就可以了!還有Toast的第一個引數this在Java中是一定要寫Activity.this的,而這裡只用寫this就可以了!

3、Kotlin檔案目錄:預設建立好的Kotlin檔案還是會放在和Java檔案一樣的位置,如果需要使kotlin檔案與Java檔案分開放的話
那麼可以在對應的gradle檔案中加入以下配置:這樣的話,所有預設建立的Kotlin檔案就會被放在/kotlin/目錄下了。
android {
   sourceSets {
       main.java.srcDirs += 'src/main/kotlin'
   }
}
4、檔案轉換:將java程式碼的,通過 Code/Conver Java File to Kotlin File 轉換成 Kotlin程式碼。另外,將Java程式碼直接複製到Kotlin檔案裡會提示,選擇轉換即可,也是非常方便的。

Kotlin 語法

下面會說一些學習 Kotlin 常見語法,其實和Java程式碼語法非常相似,比較差異很容易就能理解了,一開始難免不適應,等習慣後,相信你一定會喜歡上Kotlin語法的。

1). 宣告定義

忘掉Java的那一套寫法不然會很不適應的,Kotlin有自己的特性不該被Java的思維所束縛。在Kotlin中常量用val宣告,變了用var宣告,關鍵字在前面,型別以冒號:隔開在後面,也可以省略直接賦值,型別後帶問號?表示可為空型別(預設空安全)。
常量val延遲載入by lazy{},預設執行緒安全關閉執行緒安全lazy(LazyThreadSafetyMode.NONE){},變數var延遲載入lateinit。

//常量陣列int[][][] arrs = new int[3][2][1];
val arrs = Array(3) { Array(2) { IntArray(1) } }
//空安全變數
var str: String = "hello"
//可為空字串變數
var str1: String? = null

2). 條件

if...else 正常使用,不過移除了switch用更強大的when替代,when子式可以是各種返回Boolean的表示式。

val x = 7
when (x) {
  in 1..10 -> print("x is in the range")
  in validNumbers -> print("x is valid")
  !in 10..20 -> print("x is outside the range")
  else -> print("none of the above")
}

3). 迴圈

while 和 do...while 同Java並無區別,for則有很大改變並多出了幾個變種。

val list = ArrayList<String>()
//遞增for (int i = 0; i < list.size(); i++)
for (i in list.indices) {
   print(list[i])
}
//遞增for (int i = 2; i < list.size(); i++)
for (i in 2..list.size-1) {
   print(list[i])
}
//遞減for (int i = list.size(); i >= 0; i--)
for (i in list.size downTo 0) {
    print(list[i])
}
//操作列表內的物件
for (item in list) {
    print(item)
}
//加強版
for((i, item) in list.witnIndex()) {
    print(list[i])
    print(item)
}
//變種版
list.forEach {
    print(it)
}

list.forEach {
    print(it)
}

list.forEachIndexed { i, s ->
    print(list[i])
    print(s)
}

list.forEachIndexed(object :(Int,String) -> Unit{
    override fun invoke(i: Int, s: String) {
        print(list[i])
        print(s)
    }
})

萬能的冒號

在Kotlin中':'冒號絕對是萬能來稱呼都不為過。常量變數的型別宣告、函式的返回值、類的繼承都需要它。

//val表示常量var表示變數宣告
val name: String = "tutu" 
//省略型別說明
var age = "23"
//fun表示函式
fun getName(): String{
   return "tutu"
}
//類繼承
class UserList<E>(): ArrayList<E>() {
    //...
}

除此之外還有一個特別的地方也需要它,使用Java類的時候。Kotlin最終會還是編譯成Java位元組碼,使用到Java類是必然的,在Kotlin語法如下。

val intent = Intent(this, MainActivity::class.java)

類名 ::class.java 沒有為什麼就這麼寫記著就是

我是誰的@

除了冒號另一個重要符號 @,想必用到內部類和匿名內部類的地方一定很多,再加上支援 lambda 語法,沒有它誰告訴你this和return指的是哪一個。

class User {
    inner class State{
        fun getUser(): User{
            //返回User
            return this@User
        }
        fun getState(): State{
            //返回State
            return this@State
        }
    }
}

偷懶的方法

1). Kotlin特色
Java的getter/setter方法自動轉換成屬性,對應到Kotlin屬性的呼叫。

public class User {
    private String name;
    private String age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}

這樣一個Java類在Kotlin中只需這樣呼叫。

val user = User()
//賦值
user.name = "tutu"
user.age = "23"
//取值
val name = user.name
val age = user.age

反之Kotlin的屬性自動生成Java的 getter/setter 方法,方便在Java中呼叫,同樣的定義在Kotlin中。

class User {
    var name: String? = null
    var age: String? = null
}

我們的 getter/setter 方法有時不會這麼簡單,這就需要自定義 getter/setter 了,另起一行設定 get()/set(value) 方法,實現一個Java中常用的單例,這裡只為了展示,單例在Kotlin有更簡單的方法實現,只要在 package 級別建立一個 object 即可。

class User {
    companion object {
        @Volatile var instance: User? = null
            get() {
                if (field == null) {
                    synchronized(User::class.java) {
                        if (field == null)
                            field = User()
                    }
                }
                return field
            }
    }
    var name: String? = null
    var age: String? = null
}

自定義getter/setter重點在field,跟我們熟悉所Java的this指代當前類一樣,field指代當前引數,直接使用引數名instance代替不會報錯但單例就沒效果了

2). 字串模板
在Java中拼接字串的程式碼可讀性都很差,在Kotlin字串拼接變得非常簡潔,只需用$後面加上引數名,複雜的引數要加上{}

val user = User()
//賦值
user.name = "tutu"
user.age = "23"
//取值
val name = user.name
val age = user.age
var userInfo = "name:${user.name},  age:$age"
//輸出結果:name:tutu, age:23

3). lambda
一開始覺得lambda很高階完全看不懂,其實很簡單的就是把介面名、方法名和引數型別省掉不寫再加個 -> 罷了,明白這點了就不介紹。

空判斷

Kotlin的空安全設計對於宣告可為空的引數,在使用時要進行空判斷處理,有兩種處理方式一種像Java一樣丟擲空異常,欄位後加 !!,另一種不做處理直接跳過,欄位後加?

//型別後面加?表示可為空
var age: String? = "23" 
//丟擲空指標異常
val ageInt = age!!.toInt()
//不做處理跳過
val ages = age?.toInt()

注意事項

  • 內部類和引數預設為public,而在Java中為private。
  • 類預設為不可繼承(final),想要可被繼承要宣告為open或abstract。
  • 取消了static關鍵字,靜態方法和引數統一寫在companion object塊。
  • internal模組內可見,inner內部類。

以上僅是對使用頻率較高的語法總結,學會基本可以閱讀Kotlin程式碼,遇到點問題Google速查一下,至於智慧轉換、型別推導之類的不用說使用後喜歡自然就會了。當然這只是kotlin的基本語法,方便Java快速熟悉kotlin,深入學習還請閱讀相關資料。

最後,推薦倆個官方學習網站,知識都比較全面:

 Kotlin —— 語言中文站

 Kotlin —— 中文文件

  歡迎加入QQ群聊,一起探究學習流行技術,騷客們還等什麼!

相關文章