说明
- 可代替线程整异步
- 可控制,灵活 (控制优先级,内存占用等)
- 速度快 效率高
- 有数量上限
使用
- 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