說明
- 可代替線程整異步
- 可控制,靈活 (控制優先級,內存占用等)
- 速度快 效率高
- 有數量上限
使用
- runBlocking 一般用于測試 不建議使用
- GlobalScope.launch 全局的 生命周期跟隨application 不建議使用
- CoroutineScope(job) 用
基本使用
runBlocking {Log.i("test_coroutine","我是一個runBlocking")}Log.i("test_coroutine","我在 runBlocking 協程外 且在 協程后")GlobalScope.launch {Log.i("test_coroutine","我是一個GlobalScope")}Log.i("test_coroutine","我在 GlobalScope 協程外 且在 協程后")val job = Job()val coroutineScope = CoroutineScope(job)coroutineScope.launch {Log.i("test_coroutine","我是一個coroutineScope")}Log.i("test_coroutine","我在 coroutineScope 協程外 且在 協程后")
結果
分析
runBlocking 阻塞主線程 執行了協程后 繼續執行
GlobalScope.launch 不阻塞 繼續執行主線程 后執行協程
coroutineScope.launch 不阻塞 繼續執行主線程 后執行協程
- 增加延時,效果更明顯 delay(1000)
runBlocking {delay(1000)Log.i("test_coroutine","我是一個runBlocking")}Log.i("test_coroutine","我在 runBlocking 協程外 且在 協程后")GlobalScope.launch {delay(1000)Log.i("test_coroutine","我是一個GlobalScope")}Log.i("test_coroutine","我在 GlobalScope 協程外 且在 協程后")val job = Job()val coroutineScope = CoroutineScope(job)coroutineScope.launch {delay(1000)Log.i("test_coroutine","我是一個coroutineScope")}Log.i("test_coroutine","我在 coroutineScope 協程外 且在 協程后")
結果
分析
runBlocking 阻塞主線程 執行了協程后 繼續執行
GlobalScope.launch 協程內容最后執行
coroutineScope.launch 協程內容最后執行
1.1 協程里的掛起
val coroutineScope = CoroutineScope(Job())val job = coroutineScope.launch {delay(1000)Log.i("test_coroutine","我是一個coroutineScope") //1launch {delay(1000)Log.i("test_coroutine","我是一個coroutineScope 里的 launch") // 4delay(1000)Log.i("test_coroutine","我是一個coroutineScope 里的 launch1") //5}Log.i("test_coroutine","我是一個coroutineScope1") // 2Log.i("test_coroutine","我是一個coroutineScope2") // 3}
結果
繼續玩
val coroutineScope = CoroutineScope(Job())val job = coroutineScope.launch {delay(1000)Log.i("test_coroutine","我是一個coroutineScope") //1launch {delay(1000)Log.i("test_coroutine","我是一個coroutineScope 里的 launch") //3delay(1000)Log.i("test_coroutine","我是一個coroutineScope 里的 launch1") //5}Log.i("test_coroutine","我是一個coroutineScope1") //2delay(1500) //多了個delayLog.i("test_coroutine","我是一個coroutineScope2") //4}
結果
- join()
val coroutineScope = CoroutineScope(Job())val job = coroutineScope.launch {delay(1000)Log.i("test_coroutine","我是一個coroutineScope") //1val job1 = launch {delay(1000)Log.i("test_coroutine","我是一個coroutineScope 里的 launch") //3delay(1000)Log.i("test_coroutine","我是一個coroutineScope 里的 launch1") //4}Log.i("test_coroutine","我是一個coroutineScope1") //2job1.join()delay(1500) //多了個delayLog.i("test_coroutine","我是一個coroutineScope2") //5}
結果: 執行的時候 job1加入了進來
- cancel()
val coroutineScope = CoroutineScope(Job())val job = coroutineScope.launch {delay(1000)Log.i("test_coroutine","我是一個coroutineScope") //1val job1 = launch {delay(1000)Log.i("test_coroutine","我是一個coroutineScope 里的 launch") //3delay(1000)Log.i("test_coroutine","我是一個coroutineScope 里的 launch1") //不執行}Log.i("test_coroutine","我是一個coroutineScope1") //2delay(1500) //多了個delayLog.i("test_coroutine","我是一個coroutineScope2") //4cancel()}
結果 job 和 子job1都停了
- job1.cancel()
val coroutineScope = CoroutineScope(Job())val job = coroutineScope.launch {delay(1000)Log.i("test_coroutine","我是一個coroutineScope")val job1 = launch {delay(1000)Log.i("test_coroutine","我是一個coroutineScope 里的 launch")delay(1000)Log.i("test_coroutine","我是一個coroutineScope 里的 launch1")}Log.i("test_coroutine","我是一個coroutineScope1")delay(1500) //多了個delayLog.i("test_coroutine","我是一個coroutineScope2")job1.cancel()Log.i("test_coroutine","我是一個coroutineScope3")}
結果 job繼續執行 job1停了
- job1.cancelAndJoin() 執行完之后 取消
val coroutineScope = CoroutineScope(Job())val job = coroutineScope.launch {delay(1000)Log.i("test_coroutine","我是一個coroutineScope")val job1 = launch {var i = 0while(i<10){yield()delay(500)Log.i("test_coroutine","我是一個coroutineScope 里的 launch>>${i++}")}}Log.i("test_coroutine","我是一個coroutineScope1")delay(1500) //多了個delayLog.i("test_coroutine","我是一個coroutineScope2")job1.join()job1.cancel()Log.i("test_coroutine","我是一個coroutineScope3")}
結果 job1并沒有被取消
- job1.cancelAndJoin()
val coroutineScope = CoroutineScope(Job())val job = coroutineScope.launch {delay(1000)Log.i("test_coroutine","我是一個coroutineScope")val job1 = launch {var i = 0while(i<10){yield()delay(500)Log.i("test_coroutine","我是一個coroutineScope 里的 launch>>${i++}")}}Log.i("test_coroutine","我是一個coroutineScope1")delay(1500) //多了個delayLog.i("test_coroutine","我是一個coroutineScope2")job1.cancelAndJoin()Log.i("test_coroutine","我是一個coroutineScope3")}
結果
-
ensureActive() 在協程不在 active 狀態時會立即拋出異常。
-
yield() yield 會進行的第一個工作就是檢查任務是否完成,如果 Job 已經完成的話,就會拋出 CancellationException 來結束協程。yield 應該在定時檢查中最先被調用
-
async
val async = async {var i = 0while(i<10 && isActive){delay(500)Log.i("test_coroutine","我是一個coroutineScope 里的 launch>>${i++}")}"完事啦"}Log.i("test_coroutine","我是一個coroutineScope1")delay(1500) //多了個delayLog.i("test_coroutine","我是一個coroutineScope2")val result = async.await()Log.i("test_coroutine","我是一個coroutineScope3 result>"+result)Log.i("test_coroutine","我是一個coroutineScope4")
結果
- withTimeout
Log.i("test_coroutine","我是一個coroutineScope")withTimeout(3000){var i = 0while(i<10 && isActive){delay(500)Log.i("test_coroutine","我是一個coroutineScope 里的 launch>>${i++}")}}Log.i("test_coroutine","我是一個coroutineScope1")delay(1500) //多了個delayLog.i("test_coroutine","我是一個coroutineScope2")
結果 時間到后所在的協程也不繼續執行了
Android中的協程
- MainScope
MainScope().launch {}
- viewModelScope
implementation ‘androidx.lifecycle:lifecycle-viewmodel-android:2.8.0’
implementation ‘androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.0’
implementation ‘androidx.lifecycle:lifecycle-common:2.8.0’
viewModelScope.launch {}
- lifecycleScope
lifecycleScope.launch {}
- rememberCoroutineScope() 可能會因為組件狀態變化而移除此協程
@Composable
inline fun rememberCoroutineScope(crossinline getContext: @DisallowComposableCalls () -> CoroutineContext ={ EmptyCoroutineContext }
): CoroutineScope {val composer = currentComposerval wrapper = remember {CompositionScopedCoroutineScopeCanceller(createCompositionCoroutineScope(getContext(), composer))}return wrapper.coroutineScope
}
- currentRecomposeScope currentRecomposeScope 是一個在任何Composable函數中都能訪問的成員
作用是使當前時刻組合無效,強制觸發重組
val currentRecomposeScope: RecomposeScope@ReadOnlyComposable@OptIn(InternalComposeApi::class)@Composable get() {val scope = currentComposer.recomposeScope ?: error("no recompose scope found")currentComposer.recordUsed(scope)return scope}
- supervisorScope 協程異常不影響其他協程
- coroutineScope 有異常所有攜程都退出
本文參考 https://blog.csdn.net/Code1994/article/details/129448142