当前位置 : 主页 > 手机开发 > android >

KotlinFlow常用封装类StateFlow使用详解

来源:互联网 收集:自由互联 发布时间:2023-02-01
目录 Kotlin中StateFlow的使用 一、StateFlow的使用 二、替代LiveData 总结 Kotlin中StateFlow的使用 StateFlow 是 Flow 的实现,是一个特殊的流,默认的 Flow 是冷流,而StateFlow 是热流,和 LiveData 比较
目录
  • Kotlin中StateFlow的使用
    • 一、StateFlow的使用
    • 二、替代LiveData
  • 总结

    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自定义view实现侧滑栏详解
    下一篇:没有了
    网友评论