Kotlin之协程(第二趴)——使用协程控制界面

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)文件中。

arduino 复制代码
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

kotlin 复制代码
/**
* 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

kotlin 复制代码
/**
* 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

kotlin 复制代码
/**
* 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秒钟。相反,调度程序将安排协程在一秒钟内在下一句语句中回复。

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

相关推荐
游戏开发爱好者84 分钟前
日常开发与测试的 App 测试方法、查看设备状态、实时日志、应用数据
android·ios·小程序·https·uni-app·iphone·webview
王码码20359 分钟前
Flutter for OpenHarmony 实战之基础组件:第三十一篇 Chip 系列组件 — 灵活的标签化交互
android·flutter·交互·harmonyos
黑码哥25 分钟前
ViewHolder设计模式深度剖析:iOS开发者掌握Android列表性能优化的实战指南
android·ios·性能优化·跨平台开发·viewholder
亓才孓36 分钟前
[JDBC]元数据
android
独行soc1 小时前
2026年渗透测试面试题总结-17(题目+回答)
android·网络·安全·web安全·渗透测试·安全狮
金融RPA机器人丨实在智能1 小时前
Android Studio开发App项目进入AI深水区:实在智能Agent引领无代码交互革命
android·人工智能·ai·android studio
科技块儿1 小时前
利用IP查询在智慧城市交通信号系统中的应用探索
android·tcp/ip·智慧城市
独行soc1 小时前
2026年渗透测试面试题总结-18(题目+回答)
android·网络·安全·web安全·渗透测试·安全狮
王码码20352 小时前
Flutter for OpenHarmony 实战之基础组件:第二十七篇 BottomSheet — 动态底部弹窗与底部栏菜单
android·flutter·harmonyos
2501_915106322 小时前
app 上架过程,安装包准备、证书与描述文件管理、安装测试、上传
android·ios·小程序·https·uni-app·iphone·webview