KotlinFlow常用封装类StateFlow的使用
Kotlin中StateFlow的使用
StateFlow是Flow的实现,是一个特殊的流,默认的Flow是冷流,而StateFlow是热流,和LiveData比较类似。关于冷热流后面一期SharedFlow会详细说明。
使用StateFlow替代LiveData应该是目前很多开发者的呼吁了,确实LiveData的功能StateFlow都能实现,可以说是LiveData的升级版。
StateFlow的特点它始终是有值的。它的值是唯一的。它允许被多个观察者共用(因此是共享的数据流)。它永远只会把最新的值重现给订阅者,这与活跃观察者的数量是无关的。
官方推荐当暴露UI的状态给视图时,应该使用StateFlow。这是一种安全和高效的观察者,专门用于容纳UI状态。一、StateFlow的使用
方式一,我们自己new出来
一般我们再ViewModel中定义读写分类的StateFlowHiltViewModelclassDemo4ViewModelInjectconstructor(valsavedState:SavedStateHandle):BaseViewModel(){privatevalsearchFlowMutableStateFlow()valsearchFlow:StateFlowStringsearchFlowfunchangeSearch(keyword:String){searchFlow。valuekeyword}}
在Activity中我们就可以像类似LiveData一样的使用StateFlowprivatefuntestflow(){mViewModel。changeSearch(key)}overridefunstartObserve(){lifecycleScope。launchWhenCreated{mViewModel。searchFlow。collect{YYLogUtils。w(valueit)}}}
方式二,通过一个冷流Flow转换为StateFlowvalstateFlowflowOf(1,2,3)。stateIn(scopelifecycleScope,startedWhileSubscribed(5000,1000),startedEagerly,startedLazily,initialValue1)lifecycleScope。launch{stateFlow。collect{}}
几个重要参数的说明如下scope共享开始时所在的协程作用域范围started控制共享的开始和结束的策略Lazily:当首个订阅者出现时开始,在scope指定的作用域被结束时终止。Eagerly:立即开始,而在scope指定的作用域被结束时终止。WhileSubscribed能够指定当前不有订阅者后,多少时间取消上游数据和能够指定多少时间后,缓存中的数据被丢失,回复称initialValue的值。initialValue初始值二、替代LiveData
不管是普通的ViewModel观察订阅模式,在Activity中订阅,还是DataBinding的模式,我们都可以使用StateFlow来代替ViewModelvalwithdrawMethodMutableStateFlow(0)ImageViewandroid:ididivgirocheckedandroid:layoutwidthwrapcontentandroid:layoutheightwrapcontentandroid:layoutmarginRightdimend15dpandroid:srcdrawablepaymethodcheckedandroid:visibilitygonebinding:isVisibleGone{viewModel。withdrawMethod1}
为什么我们需要用StateFlow来代替LiveData,或者说LiveData有什么缺点?
LiveDatavsFlow
先上代码,看看它们的用法与差异
ViewModel的代码HiltViewModelclassDemo4ViewModelInjectconstructor(valsavedState:SavedStateHandle):BaseViewModel(){privatevalsearchLDMutableLiveDataString()valsearchLD:LiveDataStringsearchLDprivatevalsearchFlowMutableStateFlow()valsearchFlow:StateFlowStringsearchFlowfunchangeSearch(keyword:String){searchFlow。valuekeywordsearchLD。valuekeyword}}
Activity中触发与接收事件privatefuntestflow(){mViewModel。changeSearch(key)}overridefunstartObserve(){mViewModel。searchLD。observe(this){YYLogUtils。w(valueit)}lifecycleScope。launchWhenCreated{mViewModel。searchFlow。collect{YYLogUtils。w(valueit)}}}
可以看到基本的使用几乎是没有差异,在DataBinding中同样的是都能使用。那么它们有哪些差异呢?
它们相同的地方:仅持有单个且最新的数据自动取消订阅提供可读可写和仅可读两个版本收缩权限配合DataBinding实现双向绑定
相比StateFlow,LiveData的确定:LiveData在某些特定的场景下会丢失数据LiveData只能在主线程不能方便地支持异步化LiveData的数据变换能力远远不如FlowLiveData粘性问题解决需要额外扩展LiveData多数据源的合流能力远远不如FlowLiveData默认不支持防抖,值没有变化也会通知
这么惨,那我们开发是不是要放弃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才能把知识点串起来,期待一下。
作者:newki
链接:https:juejin。cnpost7127082531358244900