今天再講些簡單的,順便複習複習前面的東西,之後又有幾天比較硬的內容
我們每次創建coroutine都匯回傳一個job,而我們除了cancel,還可以用他的其他方法
join會等待一個job結束
val scope = launch {
delay(1000)
Timber.d("scope")
delay(1000)
Timber.d("scope")
}
launch (Dispatchers.IO){
Timber.d("io")
}
/**
* io
* scope
* scope
* */
那今天我改成這樣
val scope = launch {
delay(1000)
Timber.d("scope")
delay(1000)
Timber.d("scope")
}
scope.join()
launch (Dispatchers.IO){
Timber.d("io")
}
/**
* scope
* scope
* io
* */
可以看到他會等待該scope任務結束在執行之後的程式
joinAll
既然已經了解了join,joinAll的概念也就呼之欲出了,等待複數個job工作結束
lifecycleScope.launch {
val scope = launch {
delay(1000)
Timber.d("scope")
delay(1000)
Timber.d("scope")
}
val scope2 = launch {
delay(1000)
Timber.d("scope2")
delay(1000)
Timber.d("scope2")
}
joinAll(scope, scope2)
launch (Dispatchers.IO){
Timber.d("io")
}
}
/**
* scope
* scope2
* scope
* scope2
* io
* */
fun checkJob() {
val jjob = viewModelScope.launch {
launch {
delay(1000L)
Timber.d("in launch $this")
}
launch {
delay(1000L)
Timber.d("in launch $this")
}
}
jjob.children.forEach {
Timber.d("find child $it")
}
}
childeren可以找到該job的childrens,作為Sequence< Job>回傳,但無法找到child的child,另一方面,能找到的child,僅限以創建且還沒complete的job
以這個例子而言,如果把delay拿掉,launch作為fire and forget的coroutine,就不會被jjob.children.forEach印出
val jjob = viewModelScope.launch (start = CoroutineStart.LAZY){
launch {
delay(1000L)
Timber.d("in launch $this")
}
launch {
delay(1000L)
Timber.d("in launch $this")
}
}
Timber.d("first log")
jjob.start()
在開始coroutine這篇裡面,就有用到lazy start,不只是CoroutineScope可以用,以物件導向來理解的話,lifecycleScope和viewModelScope,可以當作繼承CoroutineScope的子類,所以用法沒甚麼區別,只有讓我們更方便而已
而start會遇到兩種情況,如果job還沒開始,就啟動coroutine,並返回true,否則返回false
val jjob = viewModelScope.launch {
while (isActive){
Timber.d("coffee")
}
while (true){
ensureActive()
Timber.d("milk")
}
}
jjob.cancel()
兩個用途差不多,反正如果不檢查直接用while(true)會無法取消,詳情看取消篇
job.cancelAndJoin()
cancels the job and waits for its completion
我們在取消篇講過,job取消不是直接取消,是會先進入canceling state,那join是等待coroutine工作完成,cancelAndJoin,就是兩個一起用
//沒騙你,這是source code
public suspend fun Job.cancelAndJoin() {
cancel()
return join()
}
這樣看來,await和join都有等待的意思,但他們差異卻很大
launch回傳的job/ join,是一組用法,他們在遇到Exception的時候,會直接向上傳遞,並且他們是阻塞式的
async/await是另一組用法,遇到Exception的時候會將存放在Deferred< T>裡面,並期待開發者呼叫await,此外其非阻塞式的用法可以併發呼叫