协程小笔记

155 阅读2分钟

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

  1. GlobalScope
  2. MainScope
  3. lifecycleScope
  4. viewModelScope
  5. runBlocking 常规函数 会阻塞主线程
  6. coroutineScope 挂起函数 协程失败会取消其他兄弟协程
  7. 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流的几种方式

  1. flow {emit(1)}

  2. (1,2,3).asFlow().collect{}

  3. flowOf(1,2,3).collect{}

    Flow最主要的作用是异步返回多个值

7. Channel

Channel实际上是一个并发安全的队列,它可以用来连接协程,实现不同协程的通信