当前位置:主页 > android教程 > Kotlin Flow封装类StateFlow

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

发布:2023-03-03 18:30:01 59


给大家整理一篇相关的编程文章,网友何英哲根据主题投稿了本篇教程内容,涉及到Kotlin、Flow封装类StateFlow、Kotlin、Flow、Kotlin Flow封装类StateFlow相关内容,已被132网友关注,相关难点技巧可以阅读下方的电子资料。

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)
    

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

LiveData vs Flow

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

ViewModel的代码

@HiltViewModel
class Demo4ViewModel @Inject constructor(
    val savedState: SavedStateHandle
) : BaseViewModel() {
    private val _searchLD = MutableLiveData()
    val searchLD: LiveData = _searchLD
    private val _searchFlow = MutableStateFlow("")
    val searchFlow: StateFlow = _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的资料请关注码农之家其它相关文章!


参考资料

相关文章

  • Kotlin泛型的使用介绍

    发布:2023-03-05

    泛型,即 "参数化类型",将类型参数化,可以用在类,接口,方法上。与 Java 一样,Kotlin 也提供泛型,为类型安全提供保证,消除类型强转的烦恼


  • Kotlin标准库函数使用分析及介绍

    发布:2023-03-06

    Kotlin提供了一个系统库,是Java库的增强。其中有很多函数在适配了Java的类型和方法同时使用Kotlin的语法。其中一些底层的函数 是使用比较广泛的


  • Kotlin扩展方法超详细介绍

    发布:2023-03-12

    Kotlin 可以为一个不能修改的或来自第三方库中的类编写一个新的函数。 这个新增的函数就像那个原始类本来就有的函数一样,可以用普通的方法调用,这种机制的函数称为扩展函数


  • kotlin协程之coroutineScope函数使用详解

    发布:2023-03-06

    这篇文章主要为大家介绍了kotlin协程之coroutineScope函数使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪


  • Kotlin线程的桥接与切换使用介绍

    发布:2023-03-03

    这篇文章主要介绍了Android开发中Kotlin线程的桥接与切换,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧


  • Kotlin语言使用WebView示例介绍

    发布:2023-03-07

    随着后台技术的不断发展,App前端的应用都布置了Web页面的界面,这个界面就是由WebView组件渲染出来的。WebView由如下优点:可以直接显示和渲染Web页面或者网页;可以直接调用网络上或者本地的html文件,也可以和JavaScript交互使用


  • 解析Kotlin接口与Java8新特性接口

    发布:2020-03-13

    这篇文章主要介绍了Kotlin 接口与 Java8 新特性接口,Kotlin的接口是可以包含属性声明。Kotlin默认的声明是fianl 和public的。Kotlin里嵌套的类默认并不是内部内,不包含对器外部类的隐式调用。下面我


  • Kotlin协程的启动方式介绍

    发布:2023-03-06

    这篇文章我们来讲协程的启动,毕竟协程是一个很强大的设计模式,深入了解需要花很多的时间,我们先从简单开始,其实学会了简单的使用,基本已经可以满足我们平时的开发需要了,话不多说,开始


网友讨论