Kotlin Flow常用封装类StateFlow使用详解

 更新时间:2022年08月31日 14:38:38   作者:newki  
这篇文章主要为大家介绍了Kotlin Flow常用封装类StateFlow使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

Kotlin中StateFlow的使用

StateFlow 是 Flow 的实现,是一个特殊的流,默认的 Flow 是冷流,而StateFlow 是热流,和 LiveData 比较类似。关于冷热流后面一期 SharedFlow 会详细说明。

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

StateFlow的特点

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

官方推荐当暴露 UI 的状态给视图时,应该使用 StateFlow。这是一种安全和高效的观察者,专门用于容纳 UI 状态。

一、StateFlow的使用

方式一,我们自己 new 出来

一般我们再ViewModel中定义读写分类的StateFlow

@HiltViewModel
class Demo4ViewModel @Inject constructor(
    val savedState: SavedStateHandle
) : BaseViewModel() {
    private val _searchFlow = MutableStateFlow("")
    val searchFlow: StateFlow<String> = _searchFlow
    fun changeSearch(keyword: String) {
        _searchFlow.value = keyword
    }
}

在Activity中我们就可以像类似 LiveData 一样的使用 StateFlow

    private fun testflow() {
       mViewModel.changeSearch("key")
    }
    override fun startObserve() {
        lifecycleScope.launchWhenCreated {
            mViewModel.searchFlow.collect {
                YYLogUtils.w("value $it")
            }
        }
    }

方式二,通过一个 冷流 Flow 转换为 StateFlow

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

几个重要参数的说明如下

  • scope 共享开始时所在的协程作用域范围
  • started 控制共享的开始和结束的策略
  • Lazily: 当首个订阅者出现时开始,在 scope 指定的作用域被结束时终止。
  • Eagerly: 立即开始,而在 scope 指定的作用域被结束时终止。
  • WhileSubscribed能够指定当前不有订阅者后,多少时间取消上游数据和能够指定多少时间后,缓存中的数据被丢失,回复称initialValue的值。
  • initialValue 初始值

二、替代LiveData

不管是普通的 ViewModel 观察订阅模式,在Activity中订阅,还是DataBinding的模式,我们都可以使用StateFlow来代替ViewModel

    val withdrawMethod = MutableStateFlow(0)
    <ImageView
        android:id="@+id/iv_giro_checked"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="@dimen/d_15dp"
        android:src="@drawable/pay_method_checked"
        android:visibility="gone"
        binding:isVisibleGone="@{viewModel.withdrawMethod == 1}" />

为什么我们需要用StateFlow来代替LiveData,或者说LiveData有什么缺点?

LiveData vs Flow

先上代码,看看它们的用法与差异

ViewModel的代码

@HiltViewModel
class Demo4ViewModel @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){
            YYLogUtils.w("value $it")
        }
        lifecycleScope.launchWhenCreated {
            mViewModel.searchFlow.collect {
                YYLogUtils.w("value $it")
            }
        }
    }

可以看到基本的使用几乎是没有差异,在DataBinding中同样的是都能使用。那么它们有哪些差异呢?

它们相同的地方:

  • 仅持有单个且最新的数据
  • 自动取消订阅
  • 提供「可读可写」和「仅可读」两个版本收缩权限
  • 配合 DataBinding 实现「双向绑定」

相比StateFlow ,LiveData的确定:

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

这么惨,那我们开发是不是要放弃LiveData了?

恰恰不是!

如果大家全部是Koltin代码开发,那么是可以用Flow,这是基于Kotlin代码,基于协程实现的,但是现在很多项目还是 Java 语言开发的。那么LiveData还是很香的。

其二是LiveData的学习成本与 协程、Flow 的学习成本不可同日而语,开发项目是整个团队的事情,不能说你一个人会一个人用,目前LiveData的简单学习成本是很有优势的。

只是我们需要在一些特定的场景慎重使用postValue,比如数据比较秘籍的场景,我们尽量使用setValue方法。

总结

如果大家的项目的语言是 Kotlin ,并且小组成员都会 Flow 。那么我推荐你们使用StateFlow 替代LiveData 。如果不是,那么 LiveData 是你最好的选择。

谷歌也只是推荐使用Flow替代LiveData。但是并没有说打算放弃 LiveData 。并且 LiveData 与 StateFlow 都有各自的使用场景,不需要担心 LiveData的 使用。

本文我们只是简单的对比,关于StateFlow 与 SharedFlow 和LiveData 三者的差异与选择,后面等SharedFlow那一期详细的讲解。

为什么很多东西都要等SharedFlow,是因为 SharedFlow 是 StateFlow 的基础,StateFlow 像是 SharedFlow 的‘青春版’。很多东西需要讲完 SharedFlow 才能把知识点串起来,更多关于Kotlin Flow封装类StateFlow的资料请关注脚本之家其它相关文章!

相关文章

  • Android实现用户头像更换操作

    Android实现用户头像更换操作

    这篇文章主要介绍了Android实现用户头像更换操作的相关资料,更改头像用户操作很简单,但是对于程序员实际操作有些复杂,需要了解的朋友可以参考下
    2016-04-04
  • Android实现读写JSON数据的方法

    Android实现读写JSON数据的方法

    这篇文章主要介绍了Android实现读写JSON数据的方法,以完整实例形式分析了Android解析及生成json数据的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-10-10
  • Android 实现ListView的点击变色的实例

    Android 实现ListView的点击变色的实例

    这篇文章主要介绍了Android 实现ListView的点击变色的实例的相关资料,主要实现Android listveiw ItemClickListener写入变色的功能,需要的朋友可以参考下
    2017-07-07
  • Android中post和get的提交方式【三种】

    Android中post和get的提交方式【三种】

    本文主要对Android中三种POST和GET的提交方式进行详细介绍。通过任何一种方式可以实现的功能是,从安卓手机端提交数据到服务器端,服务器端进行判断,并返回相应的结果。三种方式各有利弊,实现效果相同,在实际的使用过程中可以根据本身的需要进行选择。
    2016-12-12
  • Android Apk反编译及加密教程

    Android Apk反编译及加密教程

    这篇文章主要为大家介绍了Android Apk反编译及加密教程,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2022-03-03
  • Input系统之InputReader处理合成事件详解

    Input系统之InputReader处理合成事件详解

    这篇文章主要为大家介绍了Input系统之InputReader处理合成事件详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • Android—基于微信开放平台v3SDK开发(微信支付填坑)

    Android—基于微信开放平台v3SDK开发(微信支付填坑)

    这篇文章主要介绍了Android—基于微信开放平台v3SDK开发(微信支付填坑),具有一定的参考价值,有需要的可以了解一下。
    2016-11-11
  • Android MPChart自定义睡眠泳道图教程示例

    Android MPChart自定义睡眠泳道图教程示例

    这篇文章主要为大家介绍了Android MPChart自定义睡眠泳道图教程示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • 详解BadTokenException报错解决方法

    详解BadTokenException报错解决方法

    这篇文章主要介绍了BadTokenException报错的解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-08-08
  • 如何在WorkManager中处理异步任务详解

    如何在WorkManager中处理异步任务详解

    这篇文章主要给大家介绍了关于如何在WorkManager中处理异步任务的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-02-02

最新评论