# WHAT IS A COROUTINE?
## Kotlin 的 Coroutine 介紹
- Coroutine 是一種 Kotlin 中的協程概念,受到 Google 的高度支持。
- 協程的特性使其在 Android 開發中非常受歡迎。
## 函數與執行緒的背景知識
- 函數:一系列指令的執行,接受輸入並返回輸出。

- 執行緒:指示在哪個上下文中執行這些指令,通常是線性執行。


## 單執行緒的限制
- 在沒有多執行緒的情況下,所有指令會在同一個執行緒中依序執行。
- 這可能導致問題,例如進行網路請求時會凍結 UI,因為主執行緒在等待回應。
## 多執行緒的重要性
- Android 中的指令通常在主執行緒中執行,主執行緒負責更新 UI。

- 如果進行網路請求等耗時操作而不使用多執行緒,會導致 UI 停止更新。
- 因此,我們會啟動一個新的執行緒來處理這些耗時操作,避免阻塞主執行緒。

## Coroutine 的優勢

- Coroutine 可以做執行緒能做的事情,並且更高效。
- 協程是輕量級的執行緒,允許在單一執行緒中啟動多個協程。
- 協程可以暫停執行並在需要時繼續,這是執行緒無法做到的。
- 協程可以輕鬆切換上下文,即從一個執行緒切換到另一個執行緒。
## Coroutine 的效能展示
- 啟動 100,000 個協程來打印字元,執行速度非常快且不會出現內存不足錯誤。
- 相同操作用 100,000 個執行緒來執行,會導致內存不足錯誤。


# Starting our First Coroutine
## 在 Kotlin 中啟動第一個 Coroutine
- 要啟動第一個 Coroutine,首先需要在專案中加入 Coroutine 相關的依賴項目。
- 開啟 `build.gradle` 中的 `dependencies` 區塊,加入相關依賴並同步。

## 在 MainActivity 中啟動 Coroutine
- 使用 `GlobalScope.launch` 可以啟動一個 Coroutine,這是最簡單的方式,但並不是最佳方式。
- `GlobalScope` 表示這個 Coroutine 的生命週期將與整個應用程序一樣長。
## 觀察 Coroutine 的執行緒

- 可以透過 `Log.d` 來記錄 Coroutine 所在的執行緒名稱。
- 在 `GlobalScope` 中啟動的 Coroutine 將在另一個執行緒中執行,這樣可以確認 Coroutine 是異步執行的。

## 使用 Delay 暫停 Coroutine
- Coroutine 可以使用 `delay` 函數暫停指定的時間,類似於執行緒的 `sleep` 函數,但不會阻塞整個執行緒。
- `delay` 只會暫停當前的 Coroutine,不會影響同一執行緒中的其他 Coroutine。

## 主執行緒結束時的行為
- 當主執行緒結束時,所有的執行緒和 Coroutine 也會被取消,即使它們在其他執行緒中運行。
- 這可以通過延長 `delay` 時間並立即退出應用來觀察,這樣 Coroutine 的輸出就不會顯示出來。

# Suspend Functions
## Coroutine 中的 Suspend 函數介紹
- `delay` 函數是一個 `suspend` 函數,它只能在另一個 `suspend` 函數或 Coroutine 中調用。
Ctrl + Q


- 在 `GlobalScope.launch` 中啟動 Coroutine 後,可以調用 `delay` 函數來暫停 Coroutine。
## Suspend 函數的特點
- Suspend 函數只能在 Coroutine 或其他 Suspend 函數內部調用。
- 這與一般函數不同,無法在普通上下文中直接使用 Suspend 函數。
## 自定義 Suspend 函數
- 可以自定義 Suspend 函數,像這樣:


- 在 Coroutine 內部可以調用這些自定義的 Suspend 函數,模擬一些需要時間的操作,例如網絡請求。
## 多個 Suspend 函數的影響
- 當在同一 Coroutine 中依次調用多個 Suspend 函數時,它們的執行時間會累加。
- 例如,兩個各延遲 3 秒的 Suspend 函數在同一 Coroutine 中調用時,總共會延遲 6 秒。


# Coroutine Contexts
## Coroutine Context 簡介
- Coroutine 是在特定的上下文(Context)中啟動的,這個上下文決定了 Coroutine 會在哪個執行緒中運行。
- 之前我們只使用了 `GlobalScope.launch` 來啟動 Coroutine,這沒有給予我們太多的控制。
## 使用 Dispatchers 控制 Coroutine 的執行緒

| **Dispatcher** | **Dispatchers.Main** | **Dispatchers.IO** | **Dispatchers.Default** | **Dispatchers.Unconfined** |
|--------------------------|----------------------------------------------------------|---------------------------------------------------------|-------------------------------------------------------------|----------------------------------------------------------------|
| **特性** | - 主要在 Android 中使用<br>- 使用 UI 線程執行 | - 用於 I/O 密集型任務<br>- 具有比 Default 更高的線程池數量 | - 用於 CPU 密集型任務<br>- 線程池數量與 CPU 核心數相當 | - 不限於特定線程<br>- 根據掛起函數的繼續位置決定在哪個線程運行 |
| **適用場景** | - 更新 UI 元素<br>- 處理與用戶交互相關的邏輯 | - 網路請求<br>- 檔案讀寫<br>- 資料庫操作 | - 複雜的計算任務<br>- 資料處理<br>- 大型數據操作 | - 只適合簡單任務<br>- 通常用於測試或一些特殊場景 |
| **應用範例 1** | **即時天氣應用**<br>- 從 API 獲取天氣資料後,使用 `Dispatchers.Main` 將資料顯示在 UI 上,並更新天氣狀態。 | **即時天氣應用**<br>- 從 API 獲取天氣資料(如溫度、濕度)並保存到本地資料庫,使用 `Dispatchers.IO` 處理。 | **即時天氣應用**<br>- 根據多天的天氣數據進行計算,預測未來幾天的天氣趨勢和降水概率,使用 `Dispatchers.Default` 處理這些複雜計算。 | **即時天氣應用**<br>- 在開發過程中快速驗證 UI 相關行為的執行,使用 `Dispatchers.Unconfined` 進行測試。 |
| **應用範例 2** | **新聞閱讀器應用**<br>- 在加載完新聞內容後,使用 `Dispatchers.Main` 更新 UI 以顯示文章和圖片。 | **新聞閱讀器應用**<br>- 從遠程伺服器下載最新的新聞文章並儲存到本地緩存,使用 `Dispatchers.IO` 處理。 | **新聞閱讀器應用**<br>- 解析新聞資料,根據用戶的興趣生成個性化新聞推送,使用 `Dispatchers.Default` 處理這些計算。 | **新聞閱讀器應用**<br>- 在開發過程中進行快速原型設計,使用 `Dispatchers.Unconfined` 來測試文章顯示邏輯。 |
| **應用範例 3** | **健身追蹤應用**<br>- 當用戶完成運動後,使用 `Dispatchers.Main` 更新運動數據到 UI,顯示卡路里消耗等資訊。 | **健身追蹤應用**<br>- 從穿戴式設備獲取用戶的運動數據(如步數和心率),並將這些數據儲存到本地資料庫,使用 `Dispatchers.IO` 處理。 | **健身追蹤應用**<br>- 分析用戶的運動數據,生成運動報告和建議,使用 `Dispatchers.Default` 處理這些資料分析和計算。 | **健身追蹤應用**<br>- 在開發過程中快速測試不同運動算法的效果,使用 `Dispatchers.Unconfined` 進行實驗。 |
- 我們可以透過傳遞 `Dispatcher` 參數給 `launch` 函數來控制 Coroutine 的執行緒。
- 常用的 Dispatchers 包括:
- `Dispatchers.Main`: 在主執行緒中啟動 Coroutine,適合進行 UI 操作,因為只能從主執行緒更改 UI。
- `Dispatchers.IO`: 用於執行資料操作,例如網路請求、資料庫操作或檔案讀寫。
- `Dispatchers.Default`: 適合執行複雜且長時間運行的計算,避免阻塞主執行緒和 UI。
- `Dispatchers.Unconfined`: 不受限於特定執行緒,Coroutine 會在上次暫停後恢復的執行緒中繼續運行。
- `newSingleThreadContext`: 可以創建一個新的執行緒並在其中運行 Coroutine。

## 在 Coroutine 中切換上下文
- Coroutine 的強大之處在於可以輕鬆地在不同的上下文之間切換。
- 例如,我們可以在 IO Dispatcher 中執行網路請求,然後切換到 Main Dispatcher 來更新 UI。
## 例子:網路請求與 UI 更新

- 在 IO Dispatcher 中執行網路請求並獲取結果:
```kotlin
val answer = doNetworkCall()
```
- 然後使用 `withContext` 切換到 Main Dispatcher 來更新 UI:
```kotlin
withContext(Dispatchers.Main) {
tvDummy.text = answer
}
```
- 使用 `Log` 來檢查 Coroutine 執行緒的切換:
- 在 IO Dispatcher 中記錄當前執行緒:
```kotlin
Log.d("MainActivity", "Starting coroutine in thread: ${Thread.currentThread().name}")
```
- 在 Main Dispatcher 中記錄更新 UI 的執行緒:
```kotlin
Log.d("MainActivity", "Setting text in thread: ${Thread.currentThread().name}")
```
## 執行結果
- 當應用運行時,可以看到在不同的執行緒中分別執行網路請求和 UI 更新操作,確認 Coroutine Context 的有效性。
# runBlocking
## `runBlocking` 函數介紹
- `runBlocking` 函數會在主執行緒中啟動一個 Coroutine 並且會阻塞主執行緒。
- 與 `GlobalScope.launch(Dispatchers.Main)` 不同,`runBlocking` 會完全阻塞主執行緒,使 UI 更新也無法進行。
## 使用情境
- 使用 `runBlocking` 可以在主執行緒中執行 Suspend 函數,而不需要異步執行。
- 在測試中可以使用 `runBlocking` 來同步執行 Suspend 函數。
- 適合用來快速測試或了解 Coroutine 的行為。
## `runBlocking` 的執行流程
- 在 `runBlocking` 中調用 `delay` 函數,會阻塞主執行緒,類似於使用 `Thread.sleep`。
- 可以在 `runBlocking` 中使用 Suspend 函數,因為它提供了 Coroutine Scope。
## 範例與日誌驗證

- 在 `runBlocking` 區塊前後添加日誌,並在區塊內部與外部調用 `delay` 進行比較:
```kotlin
Log.d("MainActivity", "Before runBlocking")
runBlocking {
Log.d("MainActivity", "Start of runBlocking")
delay(5000)
Log.d("MainActivity", "End of runBlocking")
}
Log.d("MainActivity", "After runBlocking")
```
- 執行結果會顯示:
- `Before runBlocking`
- `Start of runBlocking`
- 延遲 5 秒
- `End of runBlocking`
- `After runBlocking`
- 移除 `runBlocking` 並改用 `Thread.sleep` 也會得到相同結果,但無法在 `Thread.sleep` 中調用 Suspend 函數。
## 在 `runBlocking` 中啟動 Coroutine

- 可以在 `runBlocking` 中啟動新的 Coroutine,這些 Coroutine 不會被阻塞,並且可以使用不同的 Dispatcher。
- 例子:
```kotlin
runBlocking {
launch(Dispatchers.IO) {
delay(3000)
Log.d("MainActivity", "Finished IO coroutine 1")
}
launch(Dispatchers.IO) {
delay(3000)
Log.d("MainActivity", "Finished IO coroutine 2")
}
Log.d("MainActivity", "End of main thread coroutine")
}
```
- 結果顯示兩個 IO Coroutine 同時結束,並在主執行緒的 Coroutine 結束後打印結果。
# Jobs, Waiting, Cancelation
## Coroutine 中的 Job 介紹
- 啟動 Coroutine 時會返回一個 `Job`。
- `Job` 可用於管理 Coroutine,如等待完成或取消。
## 等待 Coroutine 完成
- 使用 `job.join()` 等待 Coroutine 完成,阻塞當前執行緒。
- 可以在 `runBlocking` 中使用 `job.join()`。
## 範例:使用 Job 等待 Coroutine 完成
- 啟動 Coroutine 並使用 `job.join()` 等待其完成。
- 在 Coroutine 完成後再繼續執行後續程式碼。


## 取消 Coroutine 的 Job
- 使用 `job.cancel()` 來取消正在運行的 Coroutine。
- 在取消後,Coroutine 內部未完成的工作將不再執行。


## 協作式的 Coroutine 取消
- 取消 Coroutine 是協作式的,Coroutine 必須檢查取消狀態。
- 如果 Coroutine 執行長時間運算,需手動檢查是否被取消。


## 範例:手動檢查 Coroutine 取消狀態

- 當 Coroutine 執行長時間計算時,使用 `isActive` 檢查是否被取消。
## 使用 `withTimeout` 設定超時

- `withTimeout` 用於設置 Coroutine 的超時時間。
- 若 Coroutine 運行超過指定時間,將自動取消。
# Async and Await
## `async` 與 `await` 函數介紹
- `async` 和 `await` 用於在 Coroutine 中執行多個異步操作。
- 預設情況下,Coroutine 中的多個 `suspend` 函數是順序執行的。
## 範例:順序執行的問題

- 當我們執行兩個網路請求時,預設它們會一個接一個地執行,導致總耗時累加。
- 在這個範例中,每個網路請求需要 3 秒,所以總共需要 6 秒。
## 測量執行時間
- 使用 `measureTimeMillis` 來測量一段代碼的執行時間。

## 問題解決:使用 `async` 來異步執行



- 使用 `async` 啟動新的 Coroutine,允許兩個網路請求同時執行,縮短總耗時。
- `async` 返回一個 `Deferred` 對象,可用於取得計算結果。
- 使用 `await` 函數來等待 `Deferred` 的結果,而不會阻塞其他操作。
## 壞習慣的示範與優化
- 壞習慣:使用多個 `launch` 來啟動 Coroutine,並使用 `join` 來等待它們完成。
- 優化:使用 `async` 取代 `launch`,並用 `await` 來獲取結果,這種方式更簡潔且有效。
## 注意事項
- 當需要 Coroutine 返回結果時,應使用 `async` 而非 `launch`。
- 若 Coroutine 無需返回結果,則應使用 `launch`。
# lifecycleScope and viewModelScope
## Coroutine Scopes 簡介
- `GlobalScope` 用於啟動一個與應用程式生命週期相同的 Coroutine,但通常不建議使用,因為大多數情況下不需要 Coroutine 活到應用程式結束。
- 在 Android 中,有兩個非常實用的預定義 Coroutine 範圍:`LifecycleScope` 和 `ViewModelScope`。

## `LifecycleScope` 介紹
- `LifecycleScope` 允許 Coroutine 隨著 Activity 或 Fragment 的生命週期而管理。
- 當 Activity 或 Fragment 被銷毀時,所有在該 `LifecycleScope` 中啟動的 Coroutine 也會被自動取消。
## 範例:避免使用 `GlobalScope` 的問題

- 使用 `GlobalScope` 啟動 Coroutine 會導致即使 Activity 被銷毀,Coroutine 仍然繼續執行,這可能導致記憶體洩漏。
- 若 Coroutine 使用了已被銷毀的 Activity 的資源,這些資源將無法被垃圾回收。
## 修正:使用 `LifecycleScope`

- 將 `GlobalScope` 替換為 `LifecycleScope` 可以避免上述問題。
- 在 `LifecycleScope` 中啟動的 Coroutine 會隨著 Activity 被銷毀而自動取消,避免資源泄漏。
## `ViewModelScope` 介紹
- `ViewModelScope` 允許 Coroutine 隨著 ViewModel 的生命週期而管理。
- 與 `LifecycleScope` 類似,但它會讓 Coroutine 保持存活直到 ViewModel 被清除。
## 注意事項
- 若 Coroutine 執行長時間的運算且不暫停,應定期檢查是否仍處於活動狀態,以便能夠正確取消。
- `LifecycleScope` 也適用於 Fragment 的生命週期管理。
# Coroutines with Firebase Firestore
## Coroutine 與 Firebase Firestore 的結合
- 當使用 Firebase Firestore 時,經常會遇到所謂的「回調地獄」(callback hell),這是由於多個網路操作相互依賴,並且依賴回調函數來獲取數據。
- Coroutine 可以幫助解決這個問題,因為它們能夠暫停並恢復執行,不需要依賴回調函數。

## 範例:使用 Coroutine 儲存與讀取資料
- 要將 Coroutine 與 Firestore 結合使用,需要加入 `kotlinx-coroutines-play-services` 依賴。
- 透過 Coroutine,Firestore 的操作變得更為簡潔與直觀。

## 使用 Coroutine 儲存資料
- 在 Coroutine 中使用 `set` 函數將資料儲存到 Firestore 文件中,並使用 `await` 來等待操作完成。
- `await` 是一個 suspend 函數,會阻塞 Coroutine 直到操作完成。


## 使用 Coroutine 讀取資料
- 使用 `get` 函數來獲取 Firestore 文件中的資料,並使用 `await` 等待資料返回。

- 將返回的資料轉換為 Kotlin 對象後,透過 `withContext` 切換到主線程更新 UI。

## 範例總結
- Coroutine 讓 Firestore 的異步操作更加容易且避免了回調地獄。

- Coroutine 具備生命週期感知功能,可以避免在 Activity 被銷毀後仍然執行異步操作。
## 其他注意事項
- 在使用 Coroutine 處理 Firestore 操作時,確保在合適的上下文中執行,以避免不必要的資源佔用。
# Coroutines with Retrofit
## Retrofit 與 Coroutine 的結合
- 傳統上,我們使用 `enqueue` 來進行 Retrofit 網路請求,這會在一個新的執行緒中執行請求並透過回調通知結果。
- 這種方式雖然有效,但效率較低,因為會啟動一個新的執行緒。

## 使用 Coroutine 進行網路請求
- 使用 Coroutine 可以避免啟動額外的執行緒,代碼更簡潔高效。
- 可以在 Coroutine 中使用 `await` 來等待請求結果,並直接獲取資料。

## 範例:使用 Coroutine 獲取資料
- 在 Coroutine 中使用 `await` 來等待 Retrofit 請求並獲取結果,將結果直接用於後續操作。
- 如果需要處理請求錯誤,可以使用 `awaitResponse` 來獲取整個 `Response` 對象,並檢查請求是否成功。


## 優化方式:直接使用 Suspend 函數
- 可以在 Retrofit 的 API 介面中將函數定義為 `suspend` 函數,直接返回資料或 `Response` 對象,避免額外的 `Call` 包裝。
- 使用 `suspend` 函數後,Coroutine 會自動處理異步操作,代碼更簡潔,易於維護。

## 總結
- 結合 Coroutine 與 Retrofit 不僅能減少代碼量,還能提升應用程式的執行效率。
- 直接使用 `suspend` 函數讓網路請求的處理更加直觀,且簡化了錯誤處理的邏輯。
# In-Depth Guide to Coroutine Cancellation & Exception Handling
## Coroutine 中的例外處理與取消機制
- Coroutine 是處理非同步程式設計的強大工具,但當深入了解時,會發現許多陷阱,特別是在例外處理和取消機制方面。

## 基本例外處理的誤解
- 許多人認為可以直接使用 `try-catch` 區塊來捕捉 Coroutine 中的例外,但這通常無效。

- 如果例外未在 Coroutine 中直接處理(即未在引發例外的 Coroutine 中使用 `try-catch`),則例外將被傳遞到父 Coroutine,最終導致應用程序崩潰。

## Coroutine Scope 的結構
- Coroutine Scope(例如 `LifecycleScope`、`ViewModelScope`)通常會啟動一個 Coroutine,而這個 Coroutine 可以啟動子 Coroutine。
- 如果子 Coroutine 中發生未捕捉的例外,該例外將被向上傳遞到父 Coroutine,直到外層 Coroutine 捕捉該例外或應用程序崩潰。
## 例外傳遞與取消
- 當 Coroutine 被取消時,會引發 `CancellationException`,這並不會導致應用崩潰,但會被傳遞到所有相關的 Coroutine 中,以通知它們已被取消。
- 例外處理與取消機制類似,例外或取消狀態會向上傳遞,直到被適當處理。
## 使用 `launch` 與 `async` 的差異
- `launch` 用於啟動一個不需要返回值的 Coroutine,而 `async` 用於啟動一個需要返回值的 Coroutine。

- `async` 會返回一個 `Deferred`,可以使用 `await` 來獲取結果或捕捉例外。
- 如果 `async` 中發生例外,例外不會立即拋出,而是在調用 `await` 時才拋出。
## `async` 中的例外處理

- 如果在 `async` 中發生例外,例外會在調用 `await` 時被拋出,而不是立即拋出。
- 如果 `async` 的結果未被等待(未調用 `await`),則不會立即發生崩潰。
- 在調用 `await` 時,可以使用 `try-catch` 來捕捉例外。


## 錯誤的例外處理方式
- 雖然可以在 `await` 語句中使用 `try-catch` 捕捉例外,但這並不是推薦的做法。
- 存在更好的方式來處理 Coroutine 中的例外與取消機制,應避免直接在 `await` 語句中使用 `try-catch`。
## Coroutine 中的例外處理與 `CoroutineExceptionHandler`




- 當我們想處理未捕捉的例外時,可以使用 `try-catch` 區塊,但必須在引發例外的 Coroutine 內部處理,或在 `async` 的 `await` 調用時處理。
- 另一種方法是使用 `CoroutineExceptionHandler`,這是一個特定的處理器,能夠處理未捕捉的例外。
## 使用 `CoroutineExceptionHandler` 的例外處理
- 可以在 Coroutine 的根範圍內安裝 `CoroutineExceptionHandler`,以捕捉所有從子 Coroutine 傳遞上來的未捕捉例外。
- 這種方式不會處理取消例外 (`CancellationException`),因為取消例外是由 Coroutine 內部處理的,並不會導致應用崩潰。
## Coroutine 範圍:`CoroutineScope` 與 `SupervisorScope`
- 在 Coroutine 中,有兩種範圍決定子 Coroutine 的取消方式:`CoroutineScope` 和 `SupervisorScope`。
- `CoroutineScope`:當任何一個子 Coroutine 發生例外時,會取消所有的子 Coroutine 以及整個範圍。
- `SupervisorScope`:當一個子 Coroutine 發生例外時,其他子 Coroutine 不會受到影響,繼續執行。
## 範例:`CoroutineScope` 對比 `SupervisorScope`
- 使用 `CoroutineScope` 時,若一個子 Coroutine 失敗,所有子 Coroutine 都會被取消,即使已經捕捉了例外。


- 使用 `SupervisorScope` 時,若一個子 Coroutine 失敗,其他子 Coroutine 仍會繼續執行,不會因例外被取消。

| 特性 | CoroutineScope | SupervisorScope |
|--------------------------|------------------------------------------------|------------------------------------------------|
| 子協程失敗處理 | 如果任何一個子協程失敗,會取消整個範圍 (Scope) 並取消所有子協程。 | 失敗的子協程不會影響其他子協程或協程範圍 (Scope),失敗只會影響該協程。 |
| 適用情境 | 當多個子協程相互依賴且需要所有協程都成功時。 | 當多個子協程彼此獨立且不希望一個協程失敗影響其他協程時。 |
| 使用場合 | 需要管理相依的工作流程,如其中一個失敗需要全部取消。 | 需要管理獨立的工作流程,如其中一個失敗不影響整體運作。 |
| 範圍終止 | 當任何一個子協程失敗時,會取消整個範圍。 | 只有在範圍中的所有協程都完成或被手動取消時,範圍才會終止。 |
| 範例一:資料同步 App | 同步用戶資料到多個服務器,若任一伺服器同步失敗,需取消所有同步操作。 | 下載多個伺服器的資料,如果一個伺服器下載失敗,不影響其他伺服器的下載。|
| 範例二:影片處理 App | 合併多段影片,如果其中一段合併失敗,應取消整個合併過程。 | 轉換多段影片格式,如果其中一段轉換失敗,其他段落繼續轉換。 |
| 範例三:社交媒體 App | 發送多個通知至不同平台,若任一平台發送失敗,取消所有發送操作。 | 從多個社交平台拉取消息,若一個平台失敗,不影響其他平台的消息拉取。 |
## 常見錯誤:不正確的例外處理
- 在 Coroutine 中使用 `try-catch` 捕捉例外時,若捕捉了 `CancellationException`,這會導致外層範圍無法感知到取消,進而繼續執行已被取消的 Coroutine。


- 修正方法:要麼僅捕捉特定的例外(如 `HttpException`),要麼在捕捉一般例外時,檢查是否為 `CancellationException`,並重新拋出它。



## 深入理解與資源浪費問題
- 當 Coroutine 被取消時,若沒有正確處理取消例外,可能導致子 Coroutine 繼續執行,造成不必要的資源消耗。
- 通常,我們希望在取消發生時,立即終止 Coroutine 的執行,以避免資源浪費。
# [協程的例外處理](https://hackmd.io/@RainBowT/ryuTWjvjR)
# Terminology
- **Kotlin**:一種現代化、靜態類型的程式語言,由 JetBrains 開發,並且是 Android 開發的官方支援語言。
- **協程 (Coroutine)**:Kotlin 中一種輕量級的執行單位,類似於執行緒 (Thread),但更加靈活和高效。
- **函數 (Function)**:一組可重用的程式碼指令,接受輸入參數並返回輸出結果。
- **執行緒 (Thread)**:一個程序內部的執行單位,每個執行緒都可以同時執行指令。
- **主執行緒 (Main Thread)**:Android 應用中負責處理 UI 更新的主要執行緒。
- **多執行緒 (Multi-threading)**:同時執行多個執行緒的技術,可以讓程式同時處理多個任務。
- **UI 更新 (UI Update)**:在 Android 中,更新使用者界面元素的過程,通常在主執行緒中進行。
- **網路請求 (Network Call)**:應用程式向伺服器發送請求並等待回應的過程。
- **暫停 (Suspend)**:協程中可以暫時停止執行並稍後繼續的一種功能。
- **上下文切換 (Context Switching)**:協程可以從一個執行緒切換到另一個執行緒繼續執行的過程。
- **輕量級 (Lightweight)**:形容協程佔用的系統資源極少,允許大量同時執行。
- **記憶體不足錯誤 (Out of Memory Error)**:當系統無法再分配記憶體給新執行緒時發生的錯誤。
- **建構工地 (Construction Site)**:影片中的比喻,用來表示執行緒的工作環境。
- **小工人 (Little Worker)**:影片中的比喻,用來表示協程在執行緒中的工作單位。
- **指令 (Instruction)**:程式碼中的基本操作步驟。
- **平行運行 (Run in Parallel)**:多個執行緒或協程同時執行的過程。
- **程序 (Program)**:一個電腦程式的整體結構,包括所有執行緒和指令。
- **暫停執行 (Pause Execution)**:暫時停止協程的運行,並在稍後繼續。
- **程式設計師 (Programmer)**:控制協程和執行緒行為的開發者。
- **Android 應用 (Android App)**:一個在 Android 平台上運行的應用程式。
- **依賴項 (Dependencies)**:在專案中必須包含的外部庫或模組,以便使用特定功能。
- **build.gradle**:一個用於配置 Android 專案的檔案,其中定義了專案的依賴項、插件等。
- **Global Scope**:Kotlin 中的一個協程範圍,協程在這個範圍中會與應用程式的生命週期一致。
- **launch**:啟動一個新的協程,並在指定的範圍內執行一系列指令。
- **協程範圍 (Coroutine Scope)**:協程的執行上下文,決定協程的生命週期和執行範圍。
- **異步執行 (Asynchronously Execute)**:在不阻塞主執行緒的情況下執行任務。
- **Log.d**:用於在 Android 應用中輸出除錯訊息的函數。
- **tag**:在 Android 中標識除錯訊息來源的標籤,通常是類名或模組名。
- **執行緒名稱 (Thread Name)**:表示執行緒的名稱,用於辨識不同的執行緒。
- **主執行緒 (Main Thread)**:應用程式的主執行緒,負責處理 UI 更新和主要邏輯。
- **預設分派器 (Default Dispatcher)**:Kotlin 協程中的預設執行緒池,負責協程的執行。
- **延遲 (Delay)**:Kotlin 協程中的函數,用於暫停協程一段時間而不阻塞執行緒。
- **暫停 (Pause)**:暫時停止協程的執行,稍後可繼續。
- **執行緒阻塞 (Thread Blocking)**:當執行緒停止執行並等待某個事件或操作完成時的狀態。
- **sleep**:一個執行緒方法,用於暫停執行緒的執行一段時間。
- **Lockcat**:Android 中的日誌系統,用於查看應用程式的輸出訊息和錯誤。
- **預設分派器工人 (Default Dispatcher Worker)**:在預設分派器中執行工作的執行緒。
- **建構工地 (Construction Site)**:影片中的比喻,用於表示執行緒的工作環境。
- **應用程式生命週期 (Application Lifecycle)**:應用程式從啟動到結束的整個過程。
- **取消協程 (Cancel Coroutine)**:當協程範圍結束或條件觸發時,終止協程的執行。
- **協程 (Coroutine)**:Kotlin 中的輕量級執行單位,可以在一個執行緒內運行多個協程。
- **延遲 (Delay)**:協程中的一個函數,用於暫停協程執行一段時間而不阻塞執行緒。
- **全域範圍 (Global Scope)**:Kotlin 中協程的一個範圍,協程在這個範圍中會與應用程式的生命週期一致。
- **掛起函數 (Suspend Function)**:Kotlin 中一種特殊的函數,只有在協程或其他掛起函數內才能執行。
- **掛起 (Suspend)**:暫時停止協程的執行,等待特定條件達成後繼續執行。
- **網路請求 (Network Call)**:應用程式向伺服器發送請求並等待回應的過程。
- **字串 (String)**:程式設計中的一種資料型態,表示文字資料。
- **返回值 (Return Value)**:函數執行後返回的結果。
- **延遲函數 (Delay Function)**:掛起函數的一種,用於延遲協程的執行。
- **Android Studio**:Google 推出的官方集成開發環境 (IDE),用於 Android 應用程式的開發。
- **錯誤 (Error)**:程式執行過程中發生的問題,可能會導致程式停止運行。
- **執行緒 (Thread)**:一個程序內部的執行單位,每個執行緒都可以同時執行指令。
- **模擬 (Simulate)**:在程式設計中,用人為設置的環境或條件來模擬真實情況。
- **印出 (Print)**:將資料輸出到控制台或日誌系統,用於除錯或記錄。
- **日誌 (Log)**:記錄程式執行過程中產生的訊息,用於分析和除錯。
- **重複 (Duplicate)**:複製程式碼片段,使其多次出現在不同的地方。
- **掛起箭頭 (Suspend Arrow)**:在 Android Studio 中,標記掛起函數的小箭頭圖示。
- **錯誤訊息 (Error Message)**:程式發生錯誤時顯示的訊息,用於幫助開發者解決問題。
- **主執行緒 (Main Thread)**:應用程式的主執行緒,負責處理 UI 更新和主要邏輯。
- **程式模擬 (Program Simulation)**:在開發過程中,用假資料或條件模擬程式的真實運行情況。
- **協程上下文 (Coroutine Context)**:定義協程在哪個執行緒或執行環境中運行的配置。
- **分派器 (Dispatcher)**:Kotlin 協程中的一個組件,決定協程應該在哪個執行緒或執行環境中執行。
- **Global Scope**:Kotlin 中的一個協程範圍,協程在這個範圍中會與應用程式的生命週期一致。
- **Dispatchers.Main**:分派器的一種,指定協程在主執行緒(UI 執行緒)中運行,適合用於更新 UI。
- **Dispatchers.IO**:分派器的一種,適合用於執行 I/O 密集型操作,如網路請求、文件讀寫等。
- **Dispatchers.Default**:分派器的一種,適合用於執行 CPU 密集型操作,如複雜計算或長時間運行的任務。
- **Dispatchers.Unconfined**:分派器的一種,協程在任何當前的執行緒中運行,而不會固定在特定的執行緒上。
- **新單一執行緒上下文 (New Single Thread Context)**:創建一個新的執行緒,並將協程運行在該執行緒中。
- **withContext**:Kotlin 中的一個函數,用於在協程內部切換上下文,讓協程在不同的執行環境中執行。
- **延遲函數 (Delay Function)**:掛起函數的一種,用於暫停協程的執行。
- **I/O 密集型操作 (I/O Intensive Operation)**:涉及大量輸入輸出操作的任務,如網路請求和文件讀寫。
- **CPU 密集型操作 (CPU Intensive Operation)**:涉及大量計算或處理的任務,如數據處理或複雜算法運行。
- **掛起函數 (Suspend Function)**:Kotlin 中的一種特殊函數,只有在協程或其他掛起函數內才能執行。
- **主執行緒 (Main Thread)**:應用程式的主要執行緒,負責處理 UI 更新和主要邏輯。
- **執行緒名稱 (Thread Name)**:用於辨識不同執行緒的名稱。
- **鎖定日誌 (Logcat)**:Android 中的日誌系統,用於查看應用程式的輸出訊息和錯誤。
- **UI 操作 (UI Operation)**:更新或操作使用者介面元素的過程,通常需要在主執行緒中執行。
- **上下文切換 (Context Switching)**:在協程中切換執行環境或執行緒的過程。
- **假設網路請求 (Simulated Network Call)**:模擬一個網路請求,用於測試或演示。
- **UI 元素 (UI Element)**:使用者介面中的單個組件,如按鈕、文字框等。
- **協程 (Coroutine)**:Kotlin 中的輕量級執行單位,可以在一個執行緒內運行多個協程。
- **掛起函數 (Suspend Function)**:Kotlin 中一種特殊的函數,只有在協程或其他掛起函數內才能執行。
- **延遲 (Delay)**:協程中的一個函數,用於暫停協程執行一段時間而不阻塞執行緒。
- **全域範圍 (Global Scope)**:Kotlin 中的一個協程範圍,協程在這個範圍中會與應用程式的生命週期一致。
- **Dispatchers.Main**:分派器的一種,指定協程在主執行緒(UI 執行緒)中運行,適合用於更新 UI。
- **執行緒阻塞 (Thread Blocking)**:當執行緒停止執行並等待某個事件或操作完成時的狀態。
- **主執行緒 (Main Thread)**:應用程式的主要執行緒,負責處理 UI 更新和主要邏輯。
- **runBlocking**:Kotlin 中的一個函數,啟動一個新的協程並阻塞其所處的執行緒,直到協程執行完成。
- **非同步執行 (Asynchronous Execution)**:在不阻塞主執行緒的情況下執行任務,允許多個任務同時進行。
- **jUnit**:一個常用的 Java 單元測試框架,用於測試程式碼。
- **延遲函數 (Delay Function)**:掛起函數的一種,用於延遲協程的執行。
- **Logcat**:Android 中的日誌系統,用於查看應用程式的輸出訊息和錯誤。
- **執行緒名稱 (Thread Name)**:用於辨識不同執行緒的名稱。
- **IO 密集型操作 (I/O Intensive Operation)**:涉及大量輸入輸出操作的任務,如網路請求和文件讀寫。
- **CPU 密集型操作 (CPU Intensive Operation)**:涉及大量計算或處理的任務,如數據處理或複雜算法運行。
- **協程上下文 (Coroutine Context)**:定義協程在哪個執行緒或執行環境中運行的配置。
- **分派器 (Dispatcher)**:Kotlin 協程中的一個組件,決定協程應該在哪個執行緒或執行環境中執行。
- **上下文切換 (Context Switching)**:在協程中切換執行環境或執行緒的過程。
- **日誌訊息 (Log Message)**:用於記錄程式執行過程中的事件或狀態訊息。
- **同步執行 (Synchronous Execution)**:任務按順序執行,每個任務必須等待前一個任務完成。
- **UI 操作 (UI Operation)**:更新或操作使用者介面元素的過程,通常需要在主執行緒中執行。
- **協程 (Coroutine)**:Kotlin 中的輕量級執行單位,可以在一個執行緒內運行多個協程。
- **掛起函數 (Suspend Function)**:Kotlin 中一種特殊的函數,只有在協程或其他掛起函數內才能執行。
- **延遲 (Delay)**:協程中的一個函數,用於暫停協程執行一段時間而不阻塞執行緒。
- **全域範圍 (Global Scope)**:Kotlin 中的一個協程範圍,協程在這個範圍中會與應用程式的生命週期一致。
- **Dispatchers.Default**:分派器的一種,適合用於執行 CPU 密集型操作,如複雜計算或長時間運行的任務。
- **主執行緒 (Main Thread)**:應用程式的主要執行緒,負責處理 UI 更新和主要邏輯。
- **runBlocking**:Kotlin 中的一個函數,啟動一個新的協程並阻塞其所處的執行緒,直到協程執行完成。
- **非同步執行 (Asynchronous Execution)**:在不阻塞主執行緒的情況下執行任務,允許多個任務同時進行。
- **Job**:協程啟動後返回的控制單位,可以用來監控和控制協程的執行狀態。
- **join**:協程中的一個掛起函數,用來等待協程完成執行。
- **cancel**:用於取消協程的函數,可以在協程內部或外部調用。
- **取消例外 (Cancellation Exception)**:協程取消時拋出的例外,可以用來傳遞取消原因。
- **合作式取消 (Cooperative Cancellation)**:協程取消的一種方式,協程必須主動檢查並響應取消請求。
- **Fibonacci 函數**:一種遞歸算法,用於計算 Fibonacci 數列。
- **遞歸 (Recursion)**:函數在內部調用自身的一種編程技術,常用於解決重複性問題。
- **withTimeout**:Kotlin 中的一個掛起函數,設置協程執行的最大時限,超過時限將自動取消協程。
- **超時 (Timeout)**:在特定時間內未完成的操作將被終止或取消的機制。
- **測試 (Testing)**:在開發過程中檢查程式碼是否正確執行的過程。
- **Logcat**:Android 中的日誌系統,用於查看應用程式的輸出訊息和錯誤。
- **重複 (Repeat)**:一種編程結構,用於多次執行相同的代碼區塊。
- **協程 (Coroutine)**:Kotlin 中的輕量級執行單位,可以在一個執行緒內運行多個協程。
- **掛起函數 (Suspend Function)**:Kotlin 中一種特殊的函數,只有在協程或其他掛起函數內才能執行。
- **延遲 (Delay)**:協程中的一個函數,用於暫停協程執行一段時間而不阻塞執行緒。
- **非同步執行 (Asynchronous Execution)**:在不阻塞主執行緒的情況下執行任務,允許多個任務同時進行。
- **順序執行 (Sequential Execution)**:按照順序逐個執行任務,前一個任務完成後再開始下一個任務。
- **Dispatchers.IO**:分派器的一種,適合用於執行 I/O 密集型操作,如網路請求、文件讀寫等。
- **measureTimeMillis**:Kotlin 的一個函數,用於測量代碼塊的執行時間,以毫秒為單位返回時間長度。
- **全域範圍 (Global Scope)**:Kotlin 中的一個協程範圍,協程在這個範圍中會與應用程式的生命週期一致。
- **Job**:協程啟動後返回的控制單位,可以用來監控和控制協程的執行狀態。
- **join**:協程中的一個掛起函數,用來等待協程完成執行。
- **async**:Kotlin 中的一個函數,用於啟動一個協程並返回一個 deferred 物件,可以用於獲取協程的計算結果。
- **deferred**:一種特殊的協程結果容器,用於保存異步計算的結果。
- **await**:協程中的一個掛起函數,用於等待一個 deferred 物件完成並返回結果。
- **launch**:Kotlin 中的一個函數,用於啟動一個協程,但不返回任何結果,通常用於執行需要並行但不需要返回值的任務。
- **併發 (Concurrency)**:在同一時間處理多個任務或操作的能力,允許多個協程或執行緒同時運行。
- **重複 (Repeat)**:一種編程結構,用於多次執行相同的代碼區塊。
- **網路請求 (Network Call)**:應用程式向伺服器發送請求並等待回應的過程。
- **I/O 密集型操作 (I/O Intensive Operation)**:涉及大量輸入輸出操作的任務,如網路請求和文件讀寫。
- **主執行緒 (Main Thread)**:應用程式的主要執行緒,負責處理 UI 更新和主要邏輯。
- **測試 (Testing)**:在開發過程中檢查程式碼是否正確執行的過程。
- **協程 (Coroutine)**:Kotlin 中的輕量級執行單位,可以在一個執行緒內運行多個協程。
- **Global Scope**:Kotlin 中的一個協程範圍,協程在這個範圍中會與應用程式的生命週期一致,直到應用程式被銷毀為止。
- **生命週期範圍 (Lifecycle Scope)**:一種協程範圍,與 Android 活動或片段的生命週期相關聯,當活動或片段被銷毀時,範圍內的協程也會被取消。
- **ViewModel Scope**:一種協程範圍,與 ViewModel 的生命週期相關聯,當 ViewModel 被清除時,範圍內的協程也會被取消。
- **掛起函數 (Suspend Function)**:Kotlin 中一種特殊的函數,只有在協程或其他掛起函數內才能執行。
- **延遲 (Delay)**:協程中的一個函數,用於暫停協程執行一段時間而不阻塞執行緒。
- **無限迴圈 (Infinite Loop)**:一種程式結構,會持續不斷地執行某些指令,直到程式明確終止它。
- **內存洩漏 (Memory Leak)**:程式中不再需要的資源未被正確釋放,導致內存被佔用,影響應用程式性能。
- **Garbage Collection (GC)**:Java 和 Kotlin 中的自動內存管理機制,用於釋放不再使用的物件所佔用的內存空間。
- **Logcat**:Android 中的日誌系統,用於查看應用程式的輸出訊息和錯誤。
- **片段 (Fragment)**:Android 中的一種 UI 組件,能夠在活動中重複使用,並且有自己獨立的生命週期。
- **啟動意圖 (Intent)**:Android 中用於啟動活動或服務的訊息對象,包含目標活動或服務的信息。
- **onDestroy**:Android 活動或片段生命週期方法之一,當活動或片段被銷毀時調用,用於進行資源釋放等清理操作。
- **主執行緒 (Main Thread)**:應用程式的主要執行緒,負責處理 UI 更新和主要邏輯。
- **結束 (Finish)**:Android 活動中用於結束當前活動並返回到上一活動的方法。
- **協程取消 (Coroutine Cancellation)**:當協程範圍或生命週期結束時,終止協程的執行。
- **長時間運行計算 (Long-running Calculation)**:需要較長時間執行的計算任務,可能會阻塞執行緒或影響應用程式性能。
- **依賴項 (Dependencies)**:在專案中必須包含的外部庫或模組,以便使用特定功能。
- **空值 (Nullable)**:表示一個變數可以為空 (null) 的特性,在 Kotlin 中使用 `?` 表示可為空的類型。
- **協程 (Coroutine)**:Kotlin 中的輕量級執行單位,可以在一個執行緒內運行多個協程。
- **Global Scope**:Kotlin 中的一個協程範圍,協程在這個範圍中會與應用程式的生命週期一致,直到應用程式被銷毀為止。
- **Firebase Firestore**:Firebase 的雲端 NoSQL 資料庫服務,用於儲存和同步應用程式資料。
- **回呼地獄 (Callback Hell)**:嵌套多層回呼函數導致程式碼難以維護的情況,通常發生於多個異步操作依賴於彼此的情況。
- **Lambda 函數**:一種匿名函數,可以被作為參數傳遞或在程式碼中定義,用於簡化回呼函數的使用。
- **KTX**:Kotlin 擴展庫 (Kotlin Extensions),專為 Kotlin 語言設計的 API 優化,簡化了 Android 和 Firebase 的使用。
- **依賴項 (Dependencies)**:在專案中必須包含的外部庫或模組,以便使用特定功能。
- **掛起函數 (Suspend Function)**:Kotlin 中一種特殊的函數,只有在協程或其他掛起函數內才能執行。
- **等待 (Await)**:協程中的一個掛起函數,用於等待非同步任務的完成,並返回結果。
- **Task**:Firebase 操作的返回類型,表示一個非同步操作的結果。
- **toObject**:Firestore 提供的一個函數,用於將文件數據轉換為指定的 Kotlin 類型。
- **withContext**:Kotlin 中的一個函數,用於在協程內部切換上下文,讓協程在不同的執行環境中執行。
- **Logcat**:Android 中的日誌系統,用於查看應用程式的輸出訊息和錯誤。
- **生命週期範圍 (Lifecycle Scope)**:一種協程範圍,與 Android 活動或片段的生命週期相關聯,當活動或片段被銷毀時,範圍內的協程也會被取消。
- **Kotlin Data Class**:Kotlin 中一種特殊的類型,用於表示數據結構,簡化了 getter、setter 和其他常用方法的定義。
- **UI 線程 (UI Thread)**:負責處理 Android 應用程式界面更新的線程,任何界面操作都必須在此線程中執行。
- **非同步操作 (Asynchronous Operation)**:不會阻塞主線程的操作,允許在其他線程上執行任務。
- **Intent**:Android 中用於啟動活動或服務的消息對象,包含目標活動或服務的信息。
- **集合 (Collection)**:Firestore 中的數據結構,相當於數據庫中的表,包含多個文檔。
- **協程 (Coroutine)**:Kotlin 中的輕量級執行單位,可以在一個執行緒內運行多個協程。
- **Retrofit**:一個強大的 Android 和 Java HTTP 客戶端,用於網路請求和 RESTful API 通訊。
- **JSONPlaceholder**:一個免費的 REST API,用於測試和原型設計,提供虛擬的資料來測試應用程式。
- **`enqueue`**:Retrofit 的一個方法,用於非同步執行 HTTP 請求並透過回呼處理結果。
- **回呼 (Callback)**:一種常見的非同步編程模式,用於在操作完成後通知結果。
- **`await`**:Kotlin 協程中的一個掛起函數,用於等待非同步操作完成並返回結果。
- **Dispatchers.IO**:分派器的一種,適合用於執行 I/O 密集型操作,如網路請求、文件讀寫等。
- **`awaitResponse`**:Retrofit 和 Kotlin 協程一起使用時的一個方法,用於等待並返回完整的 HTTP 回應。
- **回應物件 (Response Object)**:包含 HTTP 回應資料的物件,包括狀態碼、標頭和回應主體。
- **掛起函數 (Suspend Function)**:Kotlin 中一種特殊的函數,只有在協程或其他掛起函數內才能執行。
- **API 介面 (API Interface)**:定義網路請求的接口,用於指定請求的路徑、方法和參數。
- **`Call` 物件**:Retrofit 中的一個類型,表示一次 HTTP 請求的結果,可以同步或非同步地執行。
- **非同步操作 (Asynchronous Operation)**:不會阻塞主線程的操作,允許在其他線程上執行任務。
- **`GlobalScope.launch`**:Kotlin 中的一個方法,用於啟動一個在 `GlobalScope` 範圍內運行的協程。
- **I/O 密集型操作 (I/O Intensive Operation)**:涉及大量輸入輸出操作的任務,如網路請求和文件讀寫。
- **HTTP 請求 (HTTP Request)**:用戶端向伺服器發送的請求,通常用於獲取資料或執行某些操作。
- **清單 (List)**:Kotlin 和 Java 中的一種資料結構,用於存儲有序的資料集合。
- **`Response.body()`**:用於提取 HTTP 回應的主體資料,一般為 JSON 格式的資料。
- **`isSuccessful`**:HTTP 回應的一個方法,用於檢查請求是否成功(狀態碼 200-299)。
- **API 請求 (API Call)**:應用程式通過 API 向伺服器發送請求,獲取資料或執行操作。
- **異步編程 (Asynchronous Programming)**:在不阻塞主執行緒的情況下執行任務,使多個任務可以同時進行。
- **協程範圍 (Coroutine Scope)**:協程的執行環境,定義了協程的生命週期及其取消行為。
- **`try-catch` 區塊**:用於捕獲和處理程式中可能拋出的例外情況。
- **例外傳播 (Exception Propagation)**:例外從子協程向父協程傳播,最終可能導致應用程式崩潰。
- **`CancellationException`**:協程被取消時拋出的例外,不會導致程式崩潰,但會傳播給相關協程。
- **掛起函數 (Suspend Function)**:Kotlin 中的特殊函數,必須在協程或其他掛起函數內執行。
- **`launch` 函數**:啟動一個新的協程,並返回 `Job` 物件,通常用於不需要返回值的任務。
- **`async` 函數**:啟動一個新的協程,並返回 `Deferred` 物件,用於需要返回值的任務。
- **`Job`**:協程的控制單元,用於管理協程的執行和取消。
- **`Deferred`**:`Job` 的子類,代表一個可延遲的值,可以通過 `await` 來獲取結果。
- **`await` 函數**:用於等待 `Deferred` 的結果並處理異步操作的例外。
- **`LifecycleScope`**:與 Android 活動或片段的生命週期相關聯的協程範圍。
- **協程樹 (Coroutine Tree)**:協程之間的層次結構,例外和取消會沿著這個層次結構傳播。
- **非同步例外處理 (Asynchronous Exception Handling)**:協程中的例外處理機制,與傳統同步程式不同。
- **父協程 (Parent Coroutine)**:包含其他協程的協程,負責管理其子協程的生命週期。
- **子協程 (Child Coroutine)**:由父協程啟動的協程,其生命週期受父協程管理。
- **協程取消 (Coroutine Cancellation)**:當協程範圍或生命週期結束時,終止協程的執行。
- **例外處理模式 (Exception Handling Pattern)**:協程中正確處理例外的最佳實踐和模式。
- **`supervisorScope`**:協程範圍的一種變體,允許子協程的例外不會影響其他協程。