Android Kotlin(五)数据流StateFlow和LiveData

Android 上的 Kotlin 数据流  

在协程中,与仅返回单个值的挂起函数相反,数据流可按顺序发出多个值。数据流以协程为基础构建,可提供多个值。从概念上来讲,数据流是可通过异步方式进行计算处理的一组数据序列。所发出值的类型必须相同。 

来源标注:Android 上的 Kotlin 数据流  |  Android Developers

书接上篇:

Android Kotlin知识汇总(二)最佳实践-CSDN博客Android Jetpack之LiveData 使用及源码_android livedata源码-CSDN博客Android Kotlin知识汇总(二)最佳实践-CSDN博客 


Kotlin中StateFlow的使用

在 Android 中,StateFlow 非常适合需要让可变状态保持可观察的类。

StateFlow 是 Flow 的实现。默认的 Flow 是冷流,而StateFlow 是热流和 LiveData 类似。

使用 StateFlow 替代 LiveData 应该是目前很多开发者的呼吁了,确实 LiveData 的功能 StateFlow 都能实现,可以说是 LiveData 的升级版。

但请注意,StateFlow 和 LiveData 的行为确实有所不同:

  • StateFlow 需要将初始状态传递给构造函数,而 LiveData 不需要。
  • 当 View 进入 STOPPED 状态时,LiveData.observe() 会自动取消注册使用方,而从 StateFlow 或任何其他数据流收集数据的操作并不会自动停止。

StateFlow的特点

  • 它始终是有值的。
  • 它的值是唯一的。
  • 它允许被多个观察者共用 (因此是共享的数据流)。
  • 它永远只会把最新的值重现给订阅者,这与活跃观察者的数量是无关的。 

StateFlow的设计

StateFlow是一种单数据更新的热流,通过emit方法更新StateFlow的数据,通过value属性可以获取当前的数据。

设计中,关键讲一下MutableStateFlow接口。它接口继承自StateFlow接口,并在此基础上定义了一个新方法compareAndSet, 即通过CAS的方式更新value。代码如下:

public interface MutableStateFlow<T> : StateFlow<T>, MutableSharedFlow<T> {
    // 当前数据
    public override var value: T
    // 如果except与value相等,则将value更新为update,并返回true
    // 如果except与value不相等,不做任何操作,直接返回false
    public fun compareAndSet(expect: T, update: T): Boolean
}

StateFlow的使用

方式一

在Activity中像类似LiveData 一样的使用 StateFlow。

class DemoViewModel @Inject constructor(val savedState: SavedStateHandle) : BaseViewModel() {
    private val _searchFlow = MutableStateFlow("")
    val searchFlow: StateFlow<String> = _searchFlow
    fun changeSearch(keyword: String) {
        _searchFlow.value = keyword
    }
}
private fun testflow() {
    mViewModel.changeSearch("key")
}
override fun startObserve() {
   lifecycleScope.launchWhenCreated {
       mViewModel.searchFlow.collect {
         LogUtils.w("value $it")
       }
   }
}

方式二

通过一个 冷流 Flow 转换为 StateFlow 。

val stateFlow = flowOf(1, 2, 3).stateIn(
      scope = lifecycleScope,
      started = Lazily,
      initialValue = 1
)
lifecycleScope.launch {
      stateFlow.collect {}
}

LiveData 与 StateFlow对比

先看看它们的代码的用法。

class DemoViewModel @Inject constructor(val savedState: SavedStateHandle) : BaseViewModel() {
    private val _searchLD = MutableLiveData<String>()
    val searchLD: LiveData<String> = _searchLD

    private val _searchFlow = MutableStateFlow("")
    val searchFlow: StateFlow<String> = _searchFlow

    fun changeSearch(keyword: String) {
        _searchFlow.value = keyword
        _searchLD.value = keyword
    }
}

 Activity中触发与接收事件:

private fun testflow() {
    mViewModel.changeSearch("key")
}
override fun startObserve() {
   mViewModel.searchLD.observe(this){
     LogUtils.w("value $it")
   }

   lifecycleScope.launchWhenCreated {
     mViewModel.searchFlow.collect {
      LogUtils.w("value $it")
     }
   }
}

可以看到,代码使用上十分类似。

LiveData的缺点

  • LiveData在某些特定的场景下会丢失数据
  • LiveData 只能在主线程不能方便地支持异步化
  • LiveData 的数据变换能力远远不如 Flow
  • LiveData 粘性问题解决需要额外扩展
  • LiveData 多数据源的合流能力远远不如 Flow
  • LiveData 默认不支持防抖,值没有变化也会通知

两者在开发中如何选择呢?

  • 团队内全部是Koltin代码开发,推荐使用Flow。因为基于Kotlin代码、基于协程。但是现在很多项目还是 Java 语言开发的。那么LiveData还是很香的。
  • LiveData的学习成本与协程、Flow 的学习成本不可同日而语,开发项目是整个团队的事情,不能说你一个人会一个人用,目前LiveData的简单学习成本是很有优势的。

注意:特定的场景慎重使用postValue。比如数据密集的场景,尽量使用setValue方法。

 

相关推荐

  1. Kotlin 处理livedata数据倒灌

    2024-03-13 05:58:03       25 阅读
  2. LiveDataViewModel源码学习

    2024-03-13 05:58:03       35 阅读
  3. LiveData是如何感知Room数据变化的

    2024-03-13 05:58:03       27 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-13 05:58:03       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-13 05:58:03       106 阅读
  3. 在Django里面运行非项目文件

    2024-03-13 05:58:03       87 阅读
  4. Python语言-面向对象

    2024-03-13 05:58:03       96 阅读

热门阅读

  1. LeetCode454 四数相加

    2024-03-13 05:58:03       44 阅读
  2. python安装库文件的时候一个一个安装的py脚本

    2024-03-13 05:58:03       42 阅读
  3. 内网横向渗透一般攻击技巧

    2024-03-13 05:58:03       41 阅读
  4. npm、gnvm常用命令

    2024-03-13 05:58:03       40 阅读
  5. 开源模型应用落地-安全合规篇(二)

    2024-03-13 05:58:03       41 阅读
  6. 基本sql语句

    2024-03-13 05:58:03       46 阅读
  7. 经典算法掌握

    2024-03-13 05:58:03       40 阅读
  8. proto3语言指南

    2024-03-13 05:58:03       35 阅读
  9. datax定时轮询时间小于同步处理时间怎么办?

    2024-03-13 05:58:03       35 阅读