iT邦幫忙

2021 iThome 鐵人賽

DAY 3
1
Mobile Development

解鎖kotlin coroutine的各種姿勢-新手篇系列 第 3

day3 讓我看看,什麼是Coroutine Scope

  • 分享至 

  • xImage
  •  

我想大家看到前一天的範例,應該會有這種感覺吧

唉呦,很猛嘛~
[coroutine]對呀,我超厲害的啦
這code的簡潔度,很勇喔!!
聽話,讓我看看
[coroutine]你在幹嘛,不要啦
meme

特此聲明,本系列文章沒有任何coroutine遭到迫害

正文開始

一個完整的Coroutine Scope是由下列幾個東西組成

coroutine context

  1. Job-負責控制管理一個coroutine的生命週期
  2. CoroutineDispatcher-負責控制thread之間的切換
  3. CoroutineName-你給這個coroutine取的名字,經常會在debug的時候用到
  4. CoroutineExceptionHandler- 處理在coroutine裡面發生的Exception

而他們在CoroutineScope的建構式裡,可以透過+聲明建構參數,這邊建構參數中Dispatcher和Name有默認值,CoroutineExceptionHandler則沒有,Job()就得看你是實現哪種Scope,以CoroutineScope來說,需要一個Job()

CoroutineScope(Job() + Dispatchers.IO)
// or
val scope = CoroutineScope(Job())
val job = scope.launch{
    
}

...
scope.cancel()
  1. CoroutineDispatcher 默認值是 Dispatcher.Default
  2. CoroutineName 默認值是 "coroutine"

source

淺談Job

每當我們創建一個Coroutine,他會返回一個Job,讓我們可以識別並控制Coroutine的生命週期,而我們也可以自己實例一個Job,作為Coroutine context的參數傳入,並透過這個Job管理coroutine

但回傳的job一定不會一樣,因為系統始終會分配新的job,coroutine 的父子繼承關係,我明天會講個詳細,先記住就好

Parent CoroutineContext explained

https://www.kotlincn.net/docs/reference/coroutines/coroutine-context-and-dispatchers.html

淺談Dispatcher

-IO
在主線程之外執行磁碟或網路請求,例如使用room, 從文件中讀取數據或往文件寫入數據,不同的網路操作等等
-Main
用於和界面交互和快速執行的工作,調用suspend方法、更新livedata對象等等
-Default
主線程之外,大量運用cpu資源運算的工作,如資料排序或解析json,DiffUtil等等
-Unconfined
不指定,通常會在當前的thread執行

更深入看dispatcher,jast帶你看源碼

淺談CoroutineExceptionHandler

在coroutine,任何操作如果 throw Exception,會被交由parent coroutine,然後再交給parent coroutine的parent coroutine,直到root,細節會在之後開一篇出來

為什麼這邊都用淺談的呢?
因為我覺得很重要,但全部都在這邊講又太多了,這邊就先給個概念

CoroutineScope作用

前面介紹完CoroutineScope的建構和繼承,現在講講我們為什麼要實例他
一個CoroutineScope會持續追蹤所有開發者launch或Async產生的coroutine,CoroutineScope不運行coroutine,更像是創造一個讓協程運行的作用域,,而開發者需要透過launch, async去啟用coroutine

那這樣有甚麼好處嗎?
有的,當我們針對root CoroutineScope執行scope.cancel()時,所有在他之下的Coroutine都會被取消,這是structured concurrency的特性

為了確保所有coroutine都被追蹤,kotlin僅允許以coroutineScope創建coroutine,簡單說的話,沒有scope,你用不了coroutine

某些ktx package提供了生命週期相關的coroutineScope,像是viewModelScope或是LifeCycleScope,他們是由官方提供的特殊CoroutineScope,因為他們會跟著lifecycle自動取消,而我們同樣可以創建自己的coroutineScope

val scope = CoroutineScope(Job() + Dispatchers.Main)

fun exampleMethod() {
    // Starts a new coroutine within the scope
    scope.launch {
        // New coroutine that can call suspend functions
        fetchDocs()
    }
}

fun cleanUp() {
    // Cancel the scope to cancel ongoing coroutines work
    //已取消的作用域將無法在創建協程
    scope.cancel()
}

非常重要的一點,如果你自己創建了CoroutineScope,但不去cancel掉,這個coroutine並不會被gc回收
這邊說不會被回收-stackoverFlow

連結整理

必看

官方blog
文檔

推薦看

jast帶你看源碼


上一篇
day 2 coroutine和架構組件
下一篇
day 4 I'm your father, coroutine父子繼承關係
系列文
解鎖kotlin coroutine的各種姿勢-新手篇30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言