基于阿里云,从0构建云原生应用架构与开发实战(MK分享)

30 阅读4分钟

基于阿里云,从0构建云原生应用架构与开发实战

//xia仔ke:百度网盘

运用框架中的CoroutineScope

如前所述作用域更多的要从架构角度来思索。实践上大多数时分,我们并不需求本人创立作用域,由于框架会为我们准备好。就好比Jetpack,它的作用是把UI操作的逻辑封装起来,那么ViewModel中的一切协程都应该运转在viewModelScope之中,而这是框架曾经为我们创立好了的,它会分离系统组件生命周期来管理协程。

运转上下文

协程不是什么神密的东西,也不是什么银弹,它就是一个普通的函数(例程routine),只不过它能够异步执行,也就是说launch了一个协程后,这条语句很快就执行完了,马上去执行launch {...}下面的语句了,协程代码块的执行是在协程里面,它什么时分返回结果是不晓得的。也能够挂起,协程挂起后就释放了运转它的线程,并不会阻塞运转它的线程,那么其他协程就有时机运转。

这就触及另一个重要的东西,就是协程运转的上下文,或者说协程运转的线程环境。协程它就是一个函数,它当然需求运转在某个线程里面。除非特别指定以切换运转的线程,否则一切的协程是运转在主线程中的。

协程的运转环境由,但其实根本上不会直接创立这个对象,都是经过参数或者其他构建函数来指定协程的运转上下文环境。

创立协程时指定上下文

创立协程的函数launch和async是有多个参数,一共有三个参数,最后一个当然是代码块,前面两个都是有默许值的参数,因而大局部时分能够省略,它们的完好函数签名是:

fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Job
fun  CoroutineScope.async(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> T
): Deferred

第一个参数便是指定协程运转的上下文。如今能够为我们的协程加上线程环境了:

fun main() = runBlocking {
    doWorld()
}
suspend fun doWorld() = coroutineScope {  // this: CoroutineScope
    launch(Dispatchers.Default) {
        delay(1000L)
        println(", coroutines!!")
    }
    println("Hello")
}

运用扩展函数withContext

另外一种方式就是运用,在其参数指定的上下文环境中调用代码块中的协程,等候其执行完,并返回结果。

suspend fun  withContext(context: CoroutineContext, block: suspend CoroutineScope.() -> T): T

上面的例子也能够这样写:

fun main() = runBlocking {
    doWorld()
}
suspend fun doWorld() = coroutineScope {  // this: CoroutineScope
    launch {
        withContext(Dispatchers.Default) {
            delay(1000L)
            println(", coroutines!!")
        }
    }
    println("Hello")
}

但这并不是好的用法,withContext应该用在一些suspend办法中,并且这些办法想本人指定执行环境,并且执行环境对调用方是透明的。比方说,一个担任用户操作的UesrRepository,它只向外部暴露一些suspend办法,在这些suspend办法内部经过withContext来指定它本人运转的上下文环境,从而不用管调用者的执行环境,不也需求调用者晓得repo的执行环境:

class UserRepository(
    val dispatcher: Dispatcher = Dispathers.IO
) {
    suspend fun login() {
        withContext(dispatcher) {
            // Do login
        }
    }
}

让每一个架构层次或者模块本人管理好本人运转的上下文,还有一个益处在于,能够便当的经过依赖注入来停止Mock或者测试。

运用框架中的上下文环境

固然我们能够指定,那是不是意味着要本人创立很多的context呢?非也,非也。框架中也预定义好了,能够直接拿来用,这是Kotlin中的默许线程合适做计算密集类任务;这合适做IO密集的操作,如文件读写,网络等;这是Kotlin中的主线程(即main函数运转的线程),UI中的主线程(如Swing和安卓的主线程);等等,当然了,也能够本人创立一个context。

到这里我们能够发现,现代化的并发框架较以前是是十分的完备,从创立,到管理,再到运转环境都思索的十分全面。我们如今正在学习的协程,都是如此。在Java中,其实也有相似的东西,它就是异步和并发任务运转的环境。只不过,它的API设计的还是太过原始,你依然 需求本人去完成一个并没有像RxJava中以及Kotlin中的Dispatchers一样,有一些功用明白的预定义的对象能够直接运用。