kotlin協(xié)程之coroutineScope函數(shù)使用詳解
正文
public suspend fun <R> coroutineScope(block: suspend CoroutineScope.() -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return suspendCoroutineUninterceptedOrReturn { uCont ->
val coroutine = ScopeCoroutine(uCont.context, uCont, true)
coroutine.startUndispatchedOrReturn(coroutine, block)
}
}
它是一個(gè)suspend函數(shù),創(chuàng)建一個(gè)新的協(xié)程作用域,并在該作用域內(nèi)執(zhí)行指定代碼塊,它并不啟動(dòng)協(xié)程。其存在的目的是進(jìn)行符合結(jié)構(gòu)化并發(fā)的并行分解(即,將長(zhǎng)耗時(shí)任務(wù)拆分為并發(fā)的多個(gè)短耗時(shí)任務(wù),并等待所有并發(fā)任務(wù)完成后再返回)。
coroutineScope與runBlocking的區(qū)別在于runBlocking會(huì)阻塞當(dāng)前線程,而coroutineScope會(huì)掛起所在的協(xié)程直至其內(nèi)部任務(wù)(包括子協(xié)程)執(zhí)行完成,它不會(huì)阻塞所在的線程。
coroutineScope是一個(gè)掛起函數(shù),它被掛起后,會(huì)轉(zhuǎn)而執(zhí)行之前的子協(xié)程。
fun main() = runBlocking {
launch { //launch①
delay(1000) //掛起launch①
println("test2")
}
println("test1")
coroutineScope { //第一次掛起runBlocking,直至內(nèi)部邏輯完成
launch { //launch②
delay(2000) //掛起launch②
println("test3")
}
delay(5000) //delay① //第二次掛起runBlocking
println("test4")
}
println("test5")
}
//test1
//test2
//test3
//test4
//test5
代碼分析
runBlocking在main線程創(chuàng)建并啟動(dòng)一個(gè)阻塞的協(xié)程;- 創(chuàng)建
launch①子協(xié)程,由于創(chuàng)建協(xié)程是需要一些時(shí)間的,并且協(xié)程的創(chuàng)建是由特定的線程來(lái)完成,并非是main線程。所以在創(chuàng)建協(xié)程過(guò)程中會(huì)并行地執(zhí)行后續(xù)代碼。因此test1被輸出。 - 執(zhí)行到
coroutineScope函數(shù)時(shí),把runBlocking掛起,直到內(nèi)部邏輯執(zhí)行完成。 - 然后創(chuàng)建
launch②協(xié)程,創(chuàng)建過(guò)程中執(zhí)行執(zhí)行后續(xù)代碼:delay①繼續(xù)掛起runBlocking5s(掛起函數(shù)中調(diào)用掛起函數(shù))。 - 等到
launch①創(chuàng)建完畢時(shí),把它掛起1s。launch②創(chuàng)建完畢時(shí),把它掛起2s。 - 此時(shí)
runBlocking、launch①、launch②都是被掛起狀態(tài)。 - 等到1s后
launch①恢復(fù),輸出test2;2s后launch②被恢復(fù),輸出test3;5s后runBlocking第二次掛起被恢復(fù),輸出test4。 - 此時(shí)
coroutineScope中的邏輯已經(jīng)執(zhí)行完成,恢復(fù)runBlocking的第一次掛起,test5被輸出。
這比較難以理解,下面的案例稍微容易些:
fun main() = runBlocking {
launch {
println("test3")
}
println("test1")
coroutineScope { //掛起runBlocking,直到內(nèi)部邏輯完成
println("test2")
delay(1000) //掛起runBlocking5s
println("test4")
}
println("test5") //必須等待掛起函數(shù)coroutineScope執(zhí)行完畢后才會(huì)被執(zhí)行
}
//test1
//test2
//test3
//test4
//test5
而如果把coroutineScope函數(shù)改成delay函數(shù),會(huì)更加容易理解,因?yàn)樗鼈兌际菕炱鸷瘮?shù)。
fun main() = runBlocking {
launch {
delay(1000)
println("test2")
}
println("test1")
delay(2000) //掛起runBlocking協(xié)程2s
println("test3")
}
//test1
//test2
//test3
coroutineScope經(jīng)常用來(lái)把一個(gè)長(zhǎng)耗時(shí)的任務(wù)拆分成多個(gè)子任務(wù),使這些子任務(wù)并行執(zhí)行
suspend fun showSomeData() = coroutineScope {
val data1 = async { //子任務(wù)1
delay(2000)
100
}
val data2 = async { //子任務(wù)2
delay(3000)
20
}
withContext(Dispatchers.Default) { //合并結(jié)果并返回
delay(3000)
val random = Random(10)
data1.await() + data2.await() + random.nextInt(100)
}
}
coroutineScope有如下語(yǔ)義:
- 并行執(zhí)行內(nèi)部任務(wù)
data1、data2、withContext - 如果其它任務(wù)(
random)拋出異常,data1和data2兩個(gè)任務(wù)會(huì)被取消 - 如果
showSomeData()被取消,內(nèi)部的data1、data2、withContext都會(huì)被取消 - 如果
data1、data2失敗,withContext被取消。
以上就是kotlin協(xié)程之coroutineScope函數(shù)使用詳解的詳細(xì)內(nèi)容,更多關(guān)于kotlin協(xié)程coroutineScope函數(shù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Kotlin-Coroutines中的async與await異步協(xié)程管理
- Kotlin?LinearLayout與RelativeLayout布局使用詳解
- Kotlin FrameLayout與ViewPager2控件實(shí)現(xiàn)滾動(dòng)廣告欄方法
- Kotlin協(xié)程啟動(dòng)createCoroutine及創(chuàng)建startCoroutine原理
- Android結(jié)合kotlin使用coroutine的方法實(shí)例
- Kotlin學(xué)習(xí)教程之協(xié)程Coroutine
- kotlin中泛型中in和out的區(qū)別解析
相關(guān)文章
Android編程實(shí)現(xiàn)動(dòng)態(tài)支持多語(yǔ)言的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)動(dòng)態(tài)支持多語(yǔ)言的方法,涉及Android資源、控件及屬性相關(guān)操作技巧,需要的朋友可以參考下2017-06-06
android ListView內(nèi)數(shù)據(jù)的動(dòng)態(tài)添加與刪除實(shí)例代碼
ListView內(nèi)數(shù)據(jù)的動(dòng)態(tài)添加與刪除2013-03-03
Android Studio多渠道打包、自定義打包APK名稱
Android Studio為我們提供了簡(jiǎn)便的方法,可以多渠道打包,一次打包所有的渠道包。這篇文章主要介紹了Android Studio多渠道打包、自定義打包APK名稱,需要的朋友可以參考下2018-01-01
Android HorizontalScrollView內(nèi)子控件橫向拖拽實(shí)例代碼
本文主要介紹Android HorizontalScrollView的使用,這里給大家一個(gè)實(shí)例來(lái)展示HorizontalScrollView內(nèi)子控件橫向拖拽的效果實(shí)現(xiàn),有需要的小伙伴可以參考下2016-07-07
android鬧鈴簡(jiǎn)單實(shí)現(xiàn)
本文給大家分享的是一段簡(jiǎn)單的實(shí)現(xiàn)Android系統(tǒng)的鬧鈴的代碼,非常實(shí)用,想做Android開發(fā)的小伙伴們可以參考下。2015-03-03
Android開發(fā)中關(guān)于獲取當(dāng)前Activity的一些思考
這篇文章主要為大家詳細(xì)介紹了Android開發(fā)過(guò)程中,關(guān)于獲取當(dāng)前Activity的一些思考,感興趣的小伙伴們可以參考一下2016-02-02
關(guān)于Touch Panel AA區(qū)要做外擴(kuò)的原因解析
今天小編就為大家分享一篇關(guān)于Touch Panel AA區(qū)要做外擴(kuò)的原因解析,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12
android引導(dǎo)用戶開啟自啟動(dòng)權(quán)限的方法
今天小編就為大家分享一篇android引導(dǎo)用戶開啟自啟動(dòng)權(quán)限的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-07-07

