Kotlin 协程与生命周期感知组件一起使用

一、build.gradle 引入

Kotlin 复制代码
    //CoroutineScope 生命周期感知组件 协程
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0'
    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0'
    implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.0'

二、ViewModelScope

应用中的每一个 ViewModel 都定义了 ViewModelScope 。如果 ViewModel 已清除,则在此范围内启动的协程都会取消。如果您具有仅在 ViewModel 处于活动的状态时才需要完成的工作。此时协程非常有用。如果要为布局计算某些数据,则应将工作范围限定至 ViewModel ,以便在 ViewModel 清除后,系统会自动取消工作以避免消耗资源。

您可以通过 ViewModel 的 viewModeScope 属性访问 ViewModel 的 CoroutineScope ,如下实例:

Kotlin 复制代码
class MyViewModel : ViewModel() {

    init {
        viewModelScope.launch { }
        //Coroutine that will be canceled when the ViewModel is cleared.
    }
}

三、LifecycleScope

每一个 Lifecycle 对象都定义了 LifecycleScope 。在此范围内启动的协程会在 Lifecycle 被销毁时取消。您可以通过 lifecycle.coroutineScop 或者 lifecyleOwer.lifecyleScope 属性访问 Lifecyle 的 CoroutineScope.

以下示例演示了如何使用 lifecycleScope:

Kotlin 复制代码
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        lifecycle.coroutineScope.launch {

        }
    }
}

四、可重启生命周期感知型协程

即使 lifecyleScope 提供了适当的方法以在 Lifecyle 处于 DESTROYED 状态时自动取消长时间运行的操作,但是某些情况下,您可能需要在 Lifecyle 处于某个特定状态时开始执行代码块,并在其处于其他状态时取消。例如,您可能希望在 Lifecyle 处于 STARTE 状态时收集数据流,并在其处于 STOPPED 状态时取消收集。通过此方法,应用仅在界面显示在屏幕上时才处理数据流发出操作,从而节省资源并可能避免发生应用奔溃问题。

对于这些情况, lifecycle 和 lifecycleOwner 提供了挂起 repeatOnLifecycle API 来确切实现相应操作。一下实例中的代码块会在关联的 lifecycle 至少处于 STARTED 状态时运行,并且会在 lifecycle 处于 STOPED 状态时取消运行。

Kotlin 复制代码
class MyFragment:Fragment() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        viewLifecycleOwner.lifecycleScope.launch {
            viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED){

            }
        }
    }
}

五、挂起生命周期感知型协程

即使 CoroutineScope 提供了适当的方法来自动取消长时间运行的操作,在某些情况下,您可能需要暂停执行代码块(除非 lifecycle 处于特定状态)。例如,如需运行 fragmentTransaction ,您必须等到 lifecycle 至少为 STARTED 。对于这些情况,Lifecycle 提供了其他方法: lifecycle.whenCreated、lifecycle.whenStarted 和 lifecycle.whenResumed 如果 Lifecycle 至少处于所需的最低状态,则会挂起在这些会运行的人任何协程。

以下示例包含仅当关联的 Lifecycle 至少处于 STARTED 状态时才会运行的代码块:

Kotlin 复制代码
    init {
        lifecycleScope.launch { 
            whenStarted { 
                
            }
        }
    }

如果在协程处于活动状态时通过某种 when 方法销毁了 Lifecycle , 协程会自动取消。在以下示例中,一旦 Lifecycle 状态变为 DESTROYED , finally 块即会运行:

Kotlin 复制代码
    init {
        lifecycleScope.launchWhenStarted {
            try {
                // Call some suspend functions.
            } finally {
                // This line might execute after Lifecycle is DESTROYED.
                if (lifecycle.currentState >= Lifecycle.State.STARTED) {
                    // Here, since we've checked, it is safe to run any
                    // Fragment transactions.
                }
            }
        }
    }

六、将协程与 LiveData 一起使用

使用 LiveData 时,您可能需要一步计算值。例如,您可能需要检索用户的偏好设置并将其传送给界面。在这些情况下,您可以使用 liveData 构造器函数调用 suspend 函数,并将结果作为 LiveData 对象传送。

在以下示例中,loadUser() 是在其位置声明的挂起函数。使用 liveData 构造器函数异步调用 loadUser() ,然后使用 emit() 发出去结果:

Kotlin 复制代码
class MyViewModel : ViewModel() {

    val user: LiveData<String> = liveData {
        val data = loadUser();
        emit(data)
    }

    private suspend fun loadUser(): String {
        delay(2000)
        return "name"
    }
}

liveData 构建块用作协程和 LiveData 之间的结构化并发基元。当 LiveData 变为活动状态时,代码块开始执行;当 LiveData 变为非活动状态时,代码块会在可配置的超时过后自动取消。如果代码块在完成前取消,则会在 LiveData 再次变为活动状态后重启;如果在上次运行中成功完成,则不会重启。如果代码块由于任何其他原因(例如,抛出 CancellationException)而取消,则不会重启。

您还可以从代码块中发出多个值。每次 emit() 调用都会挂起代码的执行,直到在主线程上设置 LiveData 值。

相关推荐
居居飒15 小时前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin
刘争Stanley2 天前
如何高效调试复杂布局?Layout Inspector 的 Toggle Deep Inspect 完全解析
android·kotlin·android 15·黑屏闪屏白屏
sickworm陈浩2 天前
Java 转 Kotlin 系列:究竟该不该用 lateinit?
android·kotlin
droidHZ3 天前
Compose Multiplatform 之旅—声明式UI
android·kotlin
zhangphil3 天前
Android基于Path的addRoundRect,Canvas剪切clipPath简洁的圆角矩形实现,Kotlin(1)
android·kotlin
alexhilton6 天前
Android技巧:学习使用GridLayout
android·kotlin·android jetpack
zhangphil6 天前
Android使用PorterDuffXfermode的模式PorterDuff.Mode.SRC_OUT实现橡皮擦,Kotlin(1)
android·kotlin
IH_LZH7 天前
OkHttp源码分析:分发器任务调配,拦截器责任链设计,连接池socket复用
android·java·okhttp·kotlin
casual_clover8 天前
Android之RecyclerView显示数据列表和网格
android·kotlin
氤氲息9 天前
导入kotlin
android·开发语言·kotlin