1. Activity 与 MainScope结合使用
// 实现CoroutineScope接口,MainActivity是委托对象,MainScope是被委托对象,
// 所以MainActivity可以用被委托对象的方法
// 如果不用委托,还要单独定义一个变量mainScope = MainScope()
class MainActivity : AppCompatActivity(), CoroutineScope by MainScope() {
private fun test() {
launch {
delay(2000)
}
}
override fun onDestroy() {
super.onDestroy()
cancel()
}
}
2. 协程+Retrofit+ViewModel+LiveData+DataBinding
参考: 协程上手
2024.08.13 粗浅的理解一下上面用到的技术,不一定对
协程,这就是为了异步转同步
Retrofit,网络请求,这很明显,没啥说的
ViewModel, xml中data标签中varible标签中用,还有使用viewModelScope方便
LiveData, 存储数据用的,也是更新xml中的数据,LiveData是定义在ViewModel中的
DataBind, 这就是MVVM架构必须的,activity中通过dataBinding找到对应的viewId
3. runBlocking
runBlocking是包装了一个主协程,把主线程变成主协程
4. 协程用到的几个关键api
- GlobalScope
- MainScope
- lifecycleScope
- viewModelScope
- runBlocking 常规函数 会阻塞主线程
- coroutineScope 挂起函数 协程失败会取消其他兄弟协程
- supervisorScope 挂起函数 协程失败不会影响其他兄弟协程
5. 协程小测试
以上4个函数函数打印结果分别是什么?为啥?
@Test
fun `test coroutine1` () = runBlocking{
launch {
delay(1000)
println("launch finish")
}
println("finish")
}
@Test
fun `test coroutine2` () = runBlocking{
coroutineScope {
delay(1000)
println("launch finish")
}
println("finish")
}
@Test
fun `test coroutine3` () = runBlocking{
val scope = CoroutineScope(Dispatchers.Default)
scope.launch {
delay(1000)
println("launch finish")
}
println("finish")
}
@Test
fun `test coroutine4` () = runBlocking{
val scope = CoroutineScope(Dispatchers.Default)
scope.launch {
delay(1000)
println("launch finish")
}
delay(1200)
println("finish")
}
test coroutine1 打印结果
finish
launch finish
为啥先打印finish,再打印launch finish,我认为是launch是新起了一个协程, 所以可以认为是两个协程并发执行,新协程有延时1s,所以就先打印finish,后打印launch finish
test coroutine2 打印结果 launch finish
finish
原因:coroutineScope是一个挂起函数,先执行完挂起函数,再往下执行
test coroutine3 打印结果
finish
为啥只打印了finish,没有打印launch finish,因为CoroutineScope是新的协程上下文,与runBlocking的协程上下文天不一致,这与test coroutine1是不一样的,test coroutine1虽然是2个协程,上下文是一致的,所以会等全部协程执行完函数才会结束,所以会打印launch finish,而test coroutine3不会打印launch finish
test coroutine4 打印结果
launch finish
finish
这个结果就比较好理解了,因为外部协程(父协程)延迟的时间更长,相当于等子协程执行完
6. 创建flow流的几种方式
-
flow {emit(1)}
-
(1,2,3).asFlow().collect{}
-
flowOf(1,2,3).collect{}
Flow最主要的作用是异步返回多个值
7. Channel
Channel实际上是一个并发安全的队列,它可以用来连接协程,实现不同协程的通信