1、运用协程控制界面

通过本博客将带领你编写一个协程,用于在必定延迟之后显现消息。首先,请确保您在Android Studio中打开了start模块。

1.1、了解CoroutineScope

Kotlin中,一切协程都在CoroutineScope中运转。效果域在其整个作业期间会控制协程的生命周期。假如撤销某个效果域的作业,则该效果域内发动的一切协程也将撤销。在Android上,在一些状况下,例如当用户脱离ActivityFraagment时,您能够运用效果域撤销一切正在运转的协程。效果域还允许您指定默许调度程序。调度程序能够控制哪个线程运转协程。

对于界面发动的额协程,通常在Dispatchers.Main(Android 上的主线程)上发动这类协程是正确的。在Dispatchers.Main上发动的协程在挂起期间不会堵塞主线程。因为ViewModel协程简直总是在主线程上更新界面,因而在主线程上驱动协程可防止额定的线程切换。在主线程上发动的协程可在发动后随时切换调度程序。例如,它能够运用另一个调度程序从主线程外解析大型JSON成果。

协程体统主线程安全
因为协程能够随时轻松地切换线程并将成果传递回原始线程,因而最好在主线程上发动与界面相关的协程。
运用协程时,Room和Retrofit等库原生提供主线程安全,因而您无需管理线程来进行网络或数据库调用。这往往能大幅简化代码。
但是,即使运用协程,堵塞代码(例如对列表进行排序或从文件读取数据)依然需要显现代码来创建主线程安全。假如您运用的网络或数据库(还)不支持协程,状况也是如此。

1.2、运用viewModelScope

AndroidX lifecycle-viewmodel-ktx库将CoroutineScope添加到已装备为发动界面相关协程的ViewModel中。要运用此库,您有必要将其添加到项目build.gradle(Module: start)文件中。

dependencies {
    ...
    // replace x.x.x with latest version
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:x.x.x"
}

此库将viewModelScope添加为ViewModel类的扩展函数。此效果域绑定到Dispatchers.Main,并会在清除ViewModel后主动撤销。

1.3、从线程切换到协程

MainViewModel.kt中,找到下一个TODO以及以下代码:
MainViewModel.kt

/**
* Wait one second then update the tap count.
*/
private fun updateTaps() {
    // TODO: Convert updateTaps to use coroutines
    tapCount++
    BACKGROUND.submit {
        Thread.sleep(1_000)
        _taps.postValue("$tapCount taps")
    }
}

此代码运用BACKGROUND ExecutorService(在util/Executor.kt中定义)在后台线程中运转。因为sleep会堵塞当前线程,因而,假如在主线程上调用它,会导致界面冻结。在用户点击主视图的一秒钟后,它会恳求信息提示控件。

从代码中移除BACKGROUND并从头运转代码,就能看到这种状况。加载旋转图标不会显现,并且一切内容都将在一秒钟后“跳到”最终状态。

MainViewModel.kt

/**
* Wait one second then update the tap count.
*/
private fun updateTaps() {
    // TODO: Convert updateTaps to use coroutines
    tapCount++
    Thread.sleep(1_000)
    _taps.postValue("$taoCount taps")
}

updateTaps替换为这个履行相同操作的根据协程的代码。您有必要导入launchdelay

MainViewModel.kt

/**
* Wait one second then display a snackbar.
*/
fun updateTaps() {
    // launch a coroutine in viewModelScope
    viewModelScope.launch {
        tapCount++
        // suspend this coroutine for one second
        delay(1_000)
        //  resume in the main dispatcher
        // _snackbar.value can be called directly from main thread
        _taps.postValue("$tapCount taps")
    }
}

此代码履行的操作相同,即等候1秒钟后显现信息提示控件。不过,它们存在一些重要区别:

  1. viewModelScope.launch将在viewModelScope中发动协程。这意味着,当我们传递给viewModelScope的作业撤销时,此作业/效果域内的一切写成都将撤销。假如用户在delay返回之前脱离了Activity,那么在ViewModel毁掉后体系调用onCleared时,此协程将主动撤销。
  2. 因为viewModelScope的默许调度程序为Dispatchers.Main,因而此协议将在主线程中发动。稍后,我们将了解怎么运用不同的线程。
  3. delay属性归于suspend函数。在Android Studio的左侧边线中,此函数会以图标显现。虽然此协程在主线程上运转,但delay不会堵塞此线程1秒钟。相反,调度程序将安排协程在一秒钟内涵下一句语句中回复。

开始运转测试。点击主视图后,您应该会在一秒钟后看到信息提示控件。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。