# 【Kotlin】coroutines

##### 相關資源  
[官方文件:coroutines-guide](https://kotlinlang.org/docs/coroutines-guide.html)

#### 一. 什麼是coroutines?（協同程序）

（一）意義：

- coroutines的中文翻譯為「**協程**」，「深入淺出kotlin」一書中形容協程就像「輕量的執行緒」(light-weight threads)。使用協同程序的意義就在於，啟動一個背景工作時，同時讓其他程式不需要等待工作完成就可以做別的事情，用戶體驗會比較好
- Coroutines ，分別是 cooperation + routine， cooperation 意指合作，routine 意指例行作業、慣例，照這裡直接翻譯就會是合作式例行作業。
- 協程是一種輕量級的線程，可以被掛起和恢復。它允許你以同步的方式編寫非同步程式碼，從而避免回調地獄。

（二）優點：  
1\. 解決傳統執行緒的困擾：  
影片及書本中都以「在main thread連接internet」為例，由於android明令禁止應用程式在主執行緒存取網路，因此，此時主執行緒會被阻塞。而傳統的執行序在主執行緒阻塞未被移除前，是不會再執行其他作業的，coroutines也是執行緒，只不過在這種情形會被暫停，但是不會阻塞父執行緒。

2\. 很適合執行背景工作：  
如（一）所述，使用協同程序的好處就在於，啟動一個背景工作時，同時讓其他程式不需要等待工作完成就可以做別的事情，用戶體驗會比較好。

[![image-1718866179153.png](https://bookstack.treemanou.com/uploads/images/gallery/2024-06/scaled-1680-/wh6ATNIYQLwgJSjZ-image-1718866179153.png)](https://bookstack.treemanou.com/uploads/images/gallery/2024-06/wh6ATNIYQLwgJSjZ-image-1718866179153.png)

就是我在 main thread 執行到 function A 需要等 IO thread 耗時處理的結果，那我先暫停 function A， 協調讓出 main thread 讓 main thread 去執行其他的事情，等到 IO thread 的耗時處理結束後得到結果後再回復 function A 繼續執行

#### 二.基本概念

##### 掛起函數（Suspending Function）

掛起函數是可以在不阻塞執行緒的情況下掛起的函數。它使用suspend關鍵字定義。例如：

```JavaScript
suspend fun doSomething() {
    // Your code here
}

```

##### 協程作用域（Coroutine Scope）

協程作用域管理協程的生命週期。協程只能在某個作用域內啟動。

```JavaScript
runBlocking {
    launch {
        // Coroutine code
    }
}
```

##### 啟動協程

Kotlin 提供了幾種方式來啟動協程，常用的方法有`launch`和`async`。

- launch

```JavaScript
runBlocking {
    launch {
        delay(1000L)
        println("World!")
    }
    println("Hello,")
}

// Hello
// World!
```

- async
- <span>與</span>`launch`<span>類似，但它會傳回一個</span>`Deferred`<span>對象，可以在將來取得結果。</span>

```JavaScript
runBlocking {
    val deferred = async {
        delay(1000L)
        "World!"
    }
    println("Hello,")
    println(deferred.await())
}

// Hello
// World!
```

#### <span>協程上下文與調度器</span>

<span>協程上下文包含協程的各種元素，例如調度器（Dispatcher）、作業（Job）等。</span>

- **<span>Dispatchers.Main</span>**<span>：在主執行緒上運行，用於更新UI。</span>
- **<span>Dispatchers.IO</span>**<span>：用於執行IO 操作，如網路請求、檔案讀寫。</span>
- **<span>Dispatchers.Default</span>**<span>：用於執行CPU 密集型任務。</span>
- **<span>Dispatchers.Unconfined</span>**<span>：啟動協程時繼承目前線程，只有在協程掛起後才會切換到其他線程。</span>

```JavaScript
runBlocking {
    launch(Dispatchers.Main) {
        // 在主线程运行
    }
    launch(Dispatchers.IO) {
        // 在IO线程运行
    }
    launch(Dispatchers.Default) {
        // 在默认线程池运行
    }
}
```

```JavaScript
fun main() = runBlocking { // this: CoroutineScope
    launch { // launch a new coroutine and continue
        delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
        println("World!") // print after delay
    }
    println("Hello") // main coroutine continues while a previous one is delayed
}

// Hello
// World!
```