这使得视图模型与视图解耦,允许视图经历各种生命周期状态,而不需要向观察者发送数据。 在我的ViewModels中,我通常会公开两个流来进行观察。第一个是视图状态。这个数据流定义了用户界面的状态。...然而,如果你感兴趣的话,有很多文章描述了如何用StateFlow或LiveData实现UI状态。 第二个可观察流,也是本文的重点,要有趣得多。这个数据流的目的是通知视图执行一个动作,而且只有一次。...如果没有观察者,事件必须缓冲到观察者开始消费它们。 视图可能有重要的生命周期状态,在此期间它只能安全地观察事件。因此,观察者可能并不总是在某个特定的时间点上Activity或消费流。...那么,我们如何安全地观察只在给定生命周期状态下的事件流呢?如果我们观察视图模型的事件流,比如说一个Fragment,在Fragment提供的coroutine范围内,这是否能满足我们的需要?...当生命周期被破坏时,作用域仍然会被取消,但是我们可以将观察者处于Activity状态的时间紧缩到只有启动和停止之间的生命周期状态。
而在Jetpack库中,SharedFlow 和 StateFlow 是两个处理数据流的利器,它们基于协程,提供了一种响应式的编程方式。本文将深入探讨这两个类的原理,以及在实际开发中的使用技巧。...而 StateFlow 则维护了一个可变的状态,并在状态发生变化时通知所有观察者。 热流与冷流 热流和冷流是关于数据流的两个基本概念,它们描述了数据流何时开始以及如何传递事件的方式。...观察者1从一开始就订阅,而观察者2在3秒后订阅,观察者2不会接收到观察者1在订阅之前已经接收的事件。...初始化时必须给它设置一个初始值 每次发送数据都会与上次缓存的数据作比较,只有不一样才会发送。它还可直接访问它自己的value参数获取当前结果值,在使用上与LiveData相似。...与LiveData的不同点 StateFlow必须在构建的时候传入初始值,LiveData不需要; StateFlow默认是防抖的,即相同值不更新,LiveData默认不防抖; StateFlow默认没有和生命周期绑定
欢迎点击上方"AntDream"关注我,每天进步一点点 在Kotlin的协程库kotlinx.coroutines中,StateFlow和SharedFlow是两种用于处理事件流的API,它们有相似之处...这次我们就对StateFlow和SharedFlow进行深入对比: StateFlow 和 SharedFlow 概述 StateFlow: 一种用于持有单一最新状态值并发射给多个观察者的热流。...也就是一对多的关系,可以有多个collector 同时又具有flow的所有特点,比如可以挂起,切换线程 和上面的StateFlow不同的是,这个不能主动通知collect方,需要不断emit元素,也就是利用了...流中的每个新值都会覆盖之前的值,即只有最新的状态值会被保留。 SharedFlow: 不会持有单一最新状态值(除非配置了重播缓存)。...选择指南 选择StateFlow:如果你的应用场景需要在多个观察者之间共享最新的状态,并且没有兴趣保留状态的历史记录,那么StateFlow是你的最佳选择。
Flow的生命周期管理 首先,我们接着在 Kotlin Flow响应式编程,基础知识入门 这篇文章中编写的计时器例子来继续学习。...也就是说,我们并没有很好地管理Flow的生命周期,它没有与Activity的生命周期同步,而是始终在接收着Flow上游发送过来的数据。 那这个问题要怎么解决呢?...比如说,launchWhenStarted函数就是用于保证只有在Activity处于Started状态的情况下,协程中的代码才会执行。...刚才我们也说过,StateFlow和LiveData具有高度一致性,因此可想而知,StateFlow也是粘性的。 怎么证明呢?通过一个非常简单的例子即可证明。...首先,MutableSharedFlow是不需要传入初始值参数的。因为非粘性的特性,它本身就不要求观察者在观察的那一刻就能收到消息,所以也没有传入初始值的必要。
LiveData 的历史要追溯到 2017 年。彼时,观察者模式有效简化了开发,但诸如 RxJava 一类的库对新手而言有些太过复杂。...StateFlow 与 LiveData 是最接近的,因为: 它始终是有值的。 它的值是唯一的。 它允许被多个观察者共用 (因此是共享的数据流)。...它永远只会把最新的值重现给订阅者,这与活跃观察者的数量是无关的。 当暴露 UI 的状态给视图时,应该使用 StateFlow。这是一种安全和高效的观察者,专门用于容纳 UI 状态。...Fragment.viewLifecycleOwner.lifecycleScope.launch : 立即启动协程,并且在本 Fragment 中的视图生命周期结束时取消协程。...对此,需要注意对应的协程只有在它们的生命周期所有者被销毁时才会被取消。
△ 传统的请求数据与单向数据流 响应式编程 我们将这类观察者会自动对被观察者对象的变化而作出反应的系统称之为响应式编程,它的另一个设计要点是保持数据只在一个方向上流动,因为这样更容易管理且不易出错。...在协程中我们将这种按需创建并且只有在被观察时才会发送数据的数据流称之为 冷流 (Cold Stream)。...repeatOnLifecycle 是一个接收 Lifecycle.State 作为参数的挂起函数,该 API 具有生命周期感知能力,所以能够在当生命周期进入响应状态时自动使用传递给它的代码块启动新的协程...LifecycleCoroutineScope.launchWhenX { flow.collect { … } } } } 配置变更 当您向视图暴露数据流时,必须要考虑到您正在尝试在具有不同生命周期的两个元素之间传递数据...测试数据流 测试数据流可能会比较复杂,因为要处理的对象是流式数据,这里介绍在两个不同的场景中有用的小技巧: 首先是第一个场景,被测单元依赖了数据流,那对此类场景进行测试最简单的方法就是用模拟生产者替代依赖项
常用于当生产者生产数据的速度 > 消费者消费数据的速度时的情况,可以有效提升吞吐量。...2.1 与 LiveData 比较的相同点 均提供了 可读可写 和 仅可读 两个版本:MutableStateFlow、StateFlow 与 MutableLiveData、LiveData; 允许被多个观察者观察...,即生产者对消费者可以为一对多的关系; 都只会把最新的值给到观察者,即使没有观察者,也会更新自己的值; 都会产生粘性事件问题; 都可能产生丢失值的问题; 粘性事件问题:因为 StateFlow 初始化时必须给定初始值...来说 StateFlow 默认没有和生命周期绑定,直接使用会有问题; StateFlow 默认防抖:即如果发送的值与上次相同,则生产者并不会真正发送。...与 LiveData 相比,没有和 Activity 的生命周期绑定恐怕是使用 StateFlow 最不方便的地方了。
现在,SharedFlow和StateFlow为这两个问题提供了一个解决方案。 A practical example 让我们用一个实际的用例来说明。我们的用例是获取附近的位置。...这种方法的第一个问题是对生命周期的处理,LiveData会自动为我们处理。我们在上面的例子中通过使用 launchWhenStarted {}实现了类似的行为。...SharedFlow to the rescue SharedFlow是一个允许在多个Collecter之间共享自身的流,因此对于所有同时进行的收集器来说,只有一个流被有效运行(物化)。...StateFlow也可以用来实现同样的行为:它是一个专门的SharedFlow,具有.值(它的当前状态)和特定的SharedFlow配置(约束)。我们将在后面讨论这些约束。...stateIn()不支持重放的定制。StateFlow是一个具有固定重放=1的SharedFlow。这意味着新的订阅者在订阅时将立即得到当前的状态。 stateIn()需要一个初始值。
Flow是冷流,即只有在收集端(collect)开始监听时,生产端(emit)才开始执行。 RxJava的Observable是热流,即不论是否有观察者,一旦数据产生就会推送给所有观察者。...而Flow的冷流特性使其更加灵活,可以根据需要按需产生数据,避免了不必要的计算和资源浪费。 Flow的处理机制 问题: 在使用Flow时,如何有效地处理异常情况?...参考简答: StateFlow是一种具有单一值状态的Flow,主要用于处理单一状态的场景,例如ViewModel中的UI状态。...在不同协程中更新StateFlow会有什么问题? 出发点: 这个问题考察面试者对于StateFlow的线程安全性的认识,以及在实际使用中需要注意的事项。...StateFlow时的同步性,可以有效避免竞态条件。
但选型时我们要考虑以下问题,也是LiveData被推荐使用的优势 : 是否会发生内存泄漏,观察者的生命周期遭到销毁后能否自我清理 是否支持线程切换,比如LiveData保证在主线程感知变化并更新UI 不会在观察者非活跃状态下消费事件...也可以使用repeatOnLifecycle(State) 来在UI层收集,当生命周期 的在无订阅者时会丢弃数据的特性则让其彻底无缘被选用承载必须被执行的事件 而StateFlow可以理解成特殊的SharedFlow,也就无论如何都会有上面两点问题...有点像广播,且具有两个特性: 支持一对多,即一条消息支持被多个订阅者消费 具有时效性,过期的消息没有意义且不应该被延迟消费。...这也是我花很长的篇幅去介绍解决两个问题过程的原因。只有真的痛过才会感受到选择合适架构的优势。 单向数据流,任何状态的变化都来自事件,因此更容易定位出问题。
它就像一个简化的反应式组件(例如RxJava或Kotlin的Flow),也知道视图的生命周期。...Connect Kotlin Flow (or StateFlow) to LiveData 以上是一次性的获取。...viewModelScope.coroutineContext + Dispatchers.IO ) 一旦LiveData连接到任何观察者,它就会在stateFlow上待命...如果它在之前的运行中成功完成,它不会重新启动。注意,只有在自动取消的情况下才会重新启动。如果该块因任何其他原因被取消(例如抛出一个CancellationException),它不会被重新启动。...这为我们将两种技术结合在一起提供了更大的灵活性,即LiveData观察Android生命周期的能力,以及Kotlin Flor更好的反应式操作和线程处理。
与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 activity、fragment 或 service)的生命周期。...原因很简单,一个好的框架库,会遵循 开闭与最少原则,即暴漏给开发者往往只有几个主要方法。...而在 LiveData 的设计中,observe() 和 postValue() 两个方法是离我们开发者最接近的,而了解完这两个方法,也就不难理解LiveData的底层实现,以及为其他问题解析做出铺垫。...) } 在调用 observe() 订阅 Livedata 数据更新时,这里相当于添加了一个观察者,方法内部会将我们传递的 LifecycleOwner 与 观察者 包装为一个具体的生命周期观察者 wrapper...具体可以参见美团的 LiveEventBus LiveData和Flow怎么选 这里的 Flow 通常其实指 StateFlow 与 SharedFlow 。 这个问题,也常被开发者提起。
在Kotlin中,Flow是Kotlin Coroutines库中的一个重要概念,用于处理异步和并发数据流。...Flow的类型 Kotlin中的Flow主要有以下几种类型: 1、 Cold Flow: 默认情况下,Flow是冷流(Cold Flow),即只有在收集时才会执行实际的生产操作。...flow.collect { value -> println(value) } } 2、 SharedFlow: SharedFlow是一种热流(Hot Flow),就像LiveData一样,可以同时多个观察者...val stateFlow = MutableStateFlow(0) stateFlow.value = 1 停止Flow 在某些情况下,你可能希望停止或取消一个正在进行的Flow操作。...在实际应用中,可以根据需求选择合适的方式来停止Flow。
冷流只有在订阅者 collect 数据时,才按需执行发射数据流的代码。冷流和订阅者是一对一的关系,多个订阅者间的数据流是相互独立的,一旦订阅者停止监听或者生产代码结束,数据流就自动关闭。...5.1 StateFlow 与 MutableStateFlow 接口 这里先放出这两个接口方便查看: public interface StateFlow : SharedFlow...return true } } CAS 操作: 原子性的比较与设置操作,只有在旧值与 expect 相同时返回 ture。...安全地观察 Flow 数据流 前面也提到了,Flow 不具备 LiveData 的生命周期感知能力,所以订阅者在监听 Flow 数据流时,会存在生命周期安全的问题。...可以看到,这些协程 API 只有在最后组件 / 视图销毁时才会取消协程,当视图进入后台时协程并不会被取消,Flow 会持续生产数据,并且会触发更新视图。
每一次改动LiveData都会发送通知给观察者。 另一方面,LiveData感知界面的生命周期,所以只有在界面生命周期的STARTED或者RESUMED状态才会通知观察者。...如果你一直处于后台且数据一直在变化,LiveData是不会发生通知,只有在界面再一次回到前台,这时LiveData才会发生通知且只会发送一次,数据的更新取的是最后一次的变化数据。...observer方法,该方法第一个参数是LifecyleOwner,以便让LiveData具有生命感知能力,这里要感知的是ContactsActivity,所以传入this即可。...Transform 在通知观察者数据改变之前,如果你想改变LiveData中的值类型,可以使用Transformations Transformations.map() 获取原有类型中的某个特定的类型值...那么赶紧行动起来吧,让你的App中数据也具有可观察与生命感知能力。 最后文章中的代码都可以在Github中获取到。
,但是生产过程中我们往往会借用这些基础的api实现我们复杂的逻辑处理,根据需求也推出了StateFlow和SharedFlow这两个特殊的flow。...切换线程 在flow内部不允许使用不同的ConretineContext进行emit提交数据,所以想要在内部切换线程可以通过flowOn操作符进行转换 StateFlow & ShareFlow StateFlow...这两个Flow和普通的Flow不一样, Flow我们知道,只有当调用collect的时候flow传入的函数才会执行,并且每次调用collect都会重新走一遍flow函数(本质是扩展函数),调用collect...2.lifecycleScope: 此范围内启动的协程会在 Lifecycle 被销毁时取消;也可以通过when生命周期来指定何时开启,如果 Lifecycle 未至少处于所需的最低状态,则会挂起在这些块内运行的任何协程...但是我们可以使用repeatOnLifecycle,它当离开某个生命周期的时候进行取消,符合的时候在开启一个新协程(也即会重新执行collect函数是新的订阅者)。
其作用就像是一条流水线,让观察者可以实时获取对所有可观察对象所触发的事件,也就是说以此来实现对UI的实时更新或数据、事件等实时处理。...与之前介绍RAC类似,Observable对象所触发的事件有: next,触发时将可观察对象的新值传递给观察者 completed,可观察对象的生命周期正常结束并不再响应触发事件 error,可观察对象出现错误导致其生命周期终止...此处特意把error事件放在completed事件之后,打印结果证明,观察者在触发complete事件之后不会再响应任何事件。 ?...true 的时候,才会给出动作的 Observable 序列 //第一个参数:初始化的数值为0 //第二个参数:判断条件闭包第一个元素$0是否小于等于10...在创建Observable时,在订阅任何不同的观察者之后,代码一定会添加一行 .disposed(by: disposeBag) 代码,而 disposeBag 是之前全局创建生成的let disposeBag
在Android开发中,解藕很大程度上表现为系统组件的生命周期与普通组件之间的解藕,因为普通组件在使用过程中需要依赖系统组件的的生命周期。...总的来说,Lifecycle 就是具有生命周期感知能力的组件。...三、 Lifecycle源码分析 3.1 Lifecycle注册流程 Lifecycle使用两个枚举来跟踪其关联组件的生命周期状态,这两个枚举分别是Event和State。...这个同步的过程中,前面的观察者已经通知到了,后面的观察者还没被通知,于是所有观察者之间的状态就不一致了,各观察者状态之间便产生了差异,只有第一个观察者的状态等于最后一个观察者的状态,并且等于LifecycleRegistry...然后,在while循环中,执行事件的分发逻辑。while循环中有两个比较重要的方法:dispatchEvent() 和 upEvent()。
StateFlow和SharedFlow这两个特殊的flow。...这两个Flow和普通的Flow不一样,Flow我们知道,只有当调用collect的时候flow传入的函数才会执行,并且每次调用collect都会重新走一遍flow函数(本质是扩展函数),调用collect...的时候执行这个扩展函数;但是这两个Flow不一样他们不依赖于外部调用(可配置稍后说明),他们是热流,他们发出的数据会缓存起来当有订阅者的时候再通知订阅者StateFlow 和 SharedFlow是发出状态更新并向多个使用方发出值并且可以通过...:跟随ViewModel的生命周期变化,当ViewModel观察的组件销毁调用onClear的时候自动取消协程,生命周期过长不采取一般在对数据进行处理的时候会使用2.lifecycleScope: 此范围内启动的协程会在...但是我们可以使用repeatOnLifecycle,它当离开某个生命周期的时候进行取消,符合的时候在开启一个新协程(也即会重新执行collect函数是新的订阅者)。
与常规的可观察类不同,LiveData 具有生命周期感知能力,这意味着它具有感知应用组件(如 Activity、Fragment 或 Service)的生命周期的能力,并且LiveData仅更新处于活跃生命周期状态的应用组件观察者...LiveData 具有感知观察者的生命周期能力,并且只有当观察者处于激活状态(STARTED、RESUMED)才会接收到数据更新的通知,在未激活时会自动解除注册观察者,以降低内存泄漏的风险。...在生命周期从非激活状态变为激活状态,始终保持最新数据,如后台 Activity 在返回到前台后可以立即收到数据的最新状态。 适当的配置更改。...也就是只有Observer来订阅数据的时候,才会进行转换。...,并且它是具有组件生命周期感知能力的,那它是如何观察组件生命周期变化的呢?