Kotlin协程介绍(三)创建协程 launch

通过Kotlin协程介绍(二)我们知道协程会将挂起函数(suspend函数)在编译期转换为CPS,suspend函数只能在协程或者另一个suspend中运行,那么如何创建一个协程呢?

CoroutineScope.launch

可以通过GlobalScope.launch创建并立即启动一个协程

GlobalScope.launch {
    val start = System.currentTimeMillis()
    println("start")
    delay(1000) //协程内可以调用suspend函数
    println("end ${System.currentTimeMillis() - start}")
}

我们看一下launch的函数定义

public fun CoroutineScope.launch(
    context: CoroutineContext,
    start: CoroutineStart,
    block: suspend CoroutineScope.() → Unit
): Job

launch是一个CoroutineScope的扩展函数,CoroutineScope代表协程的作用域,持有一个CoroutineContext。coroutineContext类似Thread-local的概念,用于在协程中共享某些环境变量。

public interface CoroutineScope {

    public abstract val coroutineContext: kotlin.coroutines.CoroutineContext

}

launch的第一个参数接受一个CoroutineDispatcher(CoroutineContext的子类),通过CoroutineDispatcher可以指定运行协程的线程或者线程池。例如,我们可以通过Dispatcher指定协程运行在Android主线程,执行到delay时,协程挂起,Android主线程不会被阻塞,待delay执行结束会,协程将回复在主线程的执行。

launch(UI) { //UI是kotinx-coroutine-android提供的Dispatcher,协程会被分派到UI线程执行
    prograssBar.isVisible = true
    delay(1000)
    prograssBar.isVisible = false                                           
}

Job

launch启动协程后返回一个Job代表当前协程的句柄,通过Job.cancel()可以停止协程的运行。协程内可以启动子协程,子协程的Job通过Job.attachChild关联到父协程的Job,父Job的cancel会取消所有子协程。每个CoroutineScope都有一个根节点Job,其内部launch的所有协程都是其子Job。我可以自定义CoroutineScope,通过根Job管理所有协程的生命周期,比如在android的viewmodel中,我们可以在viewmodel的onCleared时cancel其所有子协程

class MyViewModel : ViewModel() {

    private val viewModelJob = SupervisorJob()
    
    private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)
    
    override fun onCleared() {
        super.onCleared()
        viewModelJob.cancel() // Cancel 当前scope下的所有协程
    }
    
    fun launchDataLoad() {
        uiScope.launch {
            sortList()
        }
    }
    
    suspend fun sortList() = withContext(Dispatchers.Default) {
        // Heavy work
    }
}
发布了11 篇原创文章 · 获赞 1 · 访问量 273

猜你喜欢

转载自blog.csdn.net/vitaviva/article/details/104094152