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 值。

相关推荐
Kapaseker2 小时前
Compose 进阶—巧用 GraphicsLayer
android·kotlin
Kapaseker1 天前
实战 Compose 中的 IntrinsicSize
android·kotlin
A0微声z3 天前
Kotlin Multiplatform (KMP) 中使用 Protobuf
kotlin
alexhilton3 天前
使用FunctionGemma进行设备端函数调用
android·kotlin·android jetpack
lhDream4 天前
Kotlin 开发者必看!JetBrains 开源 LLM 框架 Koog 快速上手指南(含示例)
kotlin
RdoZam4 天前
Android-封装基类Activity\Fragment,从0到1记录
android·kotlin
Kapaseker4 天前
研究表明,开发者对Kotlin集合的了解不到 20%
android·kotlin
糖猫猫cc5 天前
Kite:两种方式实现动态表名
java·kotlin·orm·kite
如此风景5 天前
kotlin协程学习小计
android·kotlin
Kapaseker5 天前
你搞得懂这 15 个 Android 架构问题吗
android·kotlin