關於 Android Kotlin 基本概念的 Kotlin 快速指南

這份 Kotlin 快速指南會概略說明 Android Kotlin 基本概念課程所涵蓋的主題,並以程式碼片段提供輔助。

瞭解詳情

  • 如需完整參考資料,請參閱 Kotlin 語言說明文件
  • 如需更多可用於練習的程式碼片段,請參閱 Kotlin Koans注意:系統會將您導向由 JetBrains 開發的外部 kotlinlang.org 網站。

單元 1

Kotlin 程式

用於輸出文字的最小型 main() 程式

fun main() {
    println("Hello, world!")
}

輸出一行文字

println("This is the text to print!")

內嵌註解

// This is a comment line.
// This is another comment.

變數

// Assign once, cannot change.
val age = "5"
val name = "Rover"

// Assign and change as needed.
var roll = 6
var rolledValue: Int = 4

輸出帶有字串範本的變數

println("You are already ${age}!")
println("You are already ${age} days old, ${name}!")

資料類型

Int       // Whole positive and negative numbers and zero
String    // Piece of text between quotes
IntRange  // Setting a range such as 1..6
Boolean   // Can only be true or false

不含引數的函式

// Define the function.
fun printHello () {
    println ("Hello Kotlin")
}

// Call the function.
printHello()

含引數的函式

fun printBorder(border: String, timesToRepeat: Int) {
    repeat(timesToRepeat) {
        print(border)
    }
    println()
}

傳回值的函式

fun roll(): Int {
     val randomNumber = (1..6).random()
     return randomNumber
}

基本運算子

*     // multiplication
/     // division
+     // addition
-     // subtraction
=     // assignment

邏輯運算子

>    // greater than
<    // less than
==   // equal
>=   // greater or equal
<=   // less or equal
!=   // not equal

建立隨機數字

val randomNumber = diceRange.random()

fun roll() {
     val anotherRandomNumber = (1..6).random()
     println(randomNumber)
}

控管程式流程

使用 repeat() 重複動作

fun printBorder() {
    repeat(23) {
        print("=")
    }
}

建立 repeat() 迴圈的巢狀結構

fun printCakeBottom(age: Int, layers: Int) {
    repeat(layers) {
        repeat(age + 2) {
            print("@")
        }
        println()
    }
}

使用 if/else 的條件陳述式

fun main() {
   val num = 4
   if (num > 4) {
       println("The variable is greater than 4")
   } else if (num == 4) {
       println("The variable is equal to 4")
   } else {
       println("The variable is less than 4")
   }
}

使用 when 的條件陳述式

when (rollResult) {
    luckyNumber -> println("You won!")
    1 -> println("So sorry! You rolled a 1. Try again!")
    2 -> println("Sadly, you rolled a 2. Try again!")
    3 -> println("Unfortunately, you rolled a 3. Try again!")
    4 -> println("No luck! You rolled a 4. Try again!")
    5 -> println("Don't cry! You rolled a 5. Try again!")
    6 -> println("Apologies! you rolled a 6. Try again!")
}

when 陳述式的結果指派給變數

// Determine which drawable resource ID to use based on the dice roll.
val drawableResource = when (diceRoll) {
    1 -> R.drawable.dice_1
    2 -> R.drawable.dice_2
    3 -> R.drawable.dice_3
    4 -> R.drawable.dice_4
    5 -> R.drawable.dice_5
    else -> R.drawable.dice_6
}

類別

含屬性和方法的簡易類別

class Dice {
    var sides = 6

    fun roll() {
        val randomNumber = (1..6).random()
        println(randomNumber)
    }
}

含參數的類別

class Dice (val numSides: Int) {

    fun roll(): Int {
        val randomNumber = (1..numSides).random()
        return randomNumber
    }
}

建立執行個體

val myFirstDice = Dice(6)

單元 2

類別

抽象類別

abstract class Dwelling() {
}

含抽象屬性的抽象類別

abstract class Dwelling() {
    abstract val buildingMaterial: String
}

和抽象方法的抽象類別

abstract class Dwelling() {
    abstract fun floorArea(): Double
}

將類別設為 open,即可做為子類別使用

open class RoundHut(residents: Int) {
}

以擴充父類別的方式來建立子類別

class SquareCabin : Dwelling()

覆寫父類別的函式

override fun floorArea(): Double {
}

呼叫函式的父類別實作

override fun floorArea(): Double {
    return super.floorArea() * floors
}

清單

定義唯讀清單

val numbers = listOf(1, 2, 3, 4, 5, 6)

取得清單大小

numbers.size

取得清單的第一個項目

numbers[0]

取得反向排序的清單副本

listOf("red", "blue", "green").reversed()

定義可變動的字串清單

val entrees = mutableListOf<String>()

將項目加入可變動的清單

entrees.add("spaghetti")

修改可變動清單中的項目

entrees[0] = "lasagna"

從可變動的清單中移除項目

entrees.remove("lasagna")

迴圈

使用 for 迴圈疊代清單中的項目

for (element in myList) {
    // Perform an operation with each item
    println(element)
}

使用 while 迴圈疊代清單中的項目

var index = 0
while (index < myList.size) {
    println(myList[index])
    index++
}

字串

字串中的字元數

val name = "Android"
println(name.length)

在字串範本中使用變數

val number = 10
println("$number people")

在字串範本中使用運算式

val number = 10
val groups = 5
println("${number * groups} people")

其他

擴增指派

a += b   // a = a + b
a -= b   // a = a - b
a *= b   // a = a * b
a /= b   // a = a / b

使用 with 簡化物件存取方法

with(squareCabin) {
    println("Capacity: ${capacity}")
    println("Material: ${buildingMaterial}")
    println("Has room? ${hasRoom()}")
}

從 Kotlin 數學資料庫匯入

import kotlin.math.PI

在 Kotlin 數學資料庫中使用固定的完整名稱 (無需匯入陳述式)

kotlin.math.PI * radius * radius

同時執行鏈結呼叫 (用於存取屬性和呼叫方法)

val stringInTextField = binding.costOfService.text.toString()

函式變數的變數數量

fun addToppings(vararg val toppings: String)

程式包說明

package com.example.affirmations.model

單元 3

組合

從清單建立組合

val numbers = listOf(0, 3, 8, 4, 0, 5, 5, 8, 9, 2)
val setOfNumbers = numbers.toSet()

定義組合

val set1 = setOf(1,2,3)
val set2 = mutableSetOf(3, 4, 5)

組合運算

set1.intersect(set2) // 3
set1.union(set2) // 1, 2, 3, 4, 5

對應

定義可變動的對應

val peopleAges = mutableMapOf<String, Int>(
    "Fred" to 30,
    "Ann" to 23
)

在可變動的對應中設定值

peopleAges.put("Barbara", 42)
peopleAges["Joe"] = 51

集合運算

對集合進行疊代

peopleAges.forEach { print("${it.key} is ${it.value}, ") }
// Fred is 31, Ann is 23, Barbara is 42, Joe is 51,

轉換集合中的每個項目

println(peopleAges.map { "${it.key} is ${it.value}" }.joinToString(", ") )
// Fred is 31, Ann is 23, Barbara is 42, Joe is 51

篩選集合中的項目

val filteredNames = peopleAges.filter { it.key.length < 4 }
println(filteredNames)
// {Ann=23, Joe=51}

其他集合運算

val words = listOf("about", "acute", "balloon", "best", "brief", "class")
val filteredWords = words.filter { it.startsWith("b", ignoreCase = true) }
    .shuffled() // [brief, balloon, best]
    .take(2) // [brief, balloon]
    .sorted() // [balloon, brief]

範圍函式

let

arguments?.let {
    letterId = it.getString(LETTER).toString()
}

apply

binding?.apply {
    ...
    flavorFragment = this@FlavorFragment
}

其他

幕後屬性

private var _currentScrambledWord = "test"
val currentScrambledWord: String
    get() = _currentScrambledWord

安全呼叫

val letterId = intent?.extras?.getString("letter").toString()

Lambda 函式

val triple: (Int) -> Int = { a: Int -> a * 3 }
println(triple(5))

伴生物件


class DetailActivity: AppCompatActivity() {

    ...

    companion object {
        const val LETTER = "letter"
    }

    ...

}

// accessible outside DetailActivity
DetailActivity.LETTER

屬性委派

// syntax
var <property-name> : <property-type> by <delegate-class>()
// example
private val viewModel: GameViewModel by viewModels()

延遲初始化

private var wordsList: MutableList<String> = mutableListOf() // has a value at initialization
private lateinit var currentWord: String // needs to be assigned after initialization

Elvis 運算子

var quantity : Int? = null
quantity ?: 0 // 0
quantity = 4
quantity ?: 0 // 4

單元 4

協同程式

宣告懸置函式

suspend fun getValue(): Double {
    // long running work or calls to other suspend functions
}

在 GlobalScope 中執行懸置函式

GlobalScope.launch {
    val output = getValue()
}

透過其他懸置函式呼叫懸置函式

suspend fun processValue() {
    val value = getValue()
    // modify the value
}

存取協同程式 Job

val job: Job = GlobalScope.launch {
    val output = getValue()
}

取消協同程式 Job

job.cancel()

執行懸置函式,並封鎖目前的執行緒,直到函式完成為止

runBlocking {
    val output = getValue()
}

以非同步方式延後執行懸置函式

runBlocking {
    val output = await { getValue() }

    println("Output is ${output.await()}")
}

其他

宣告物件

object DataProviderManager {

}

攔截例外狀況

try {
    // code that may throw an error
} catch (exception: Exception) {
    // handle the thrown exception
}

建立列舉類別

enum class Direction {
    NORTH, SOUTH, WEST, EAST
}

存取列舉類別值

val direction = Direction.NORTH

檢查列舉值

when (direction) {
    Directon.NORTH -> {

    }
    Direction.SOUTH -> {

    }
    Direction.WEST -> {

    }
    Direction.EAST -> {

    }
}