首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Kotlin流:当片段不可见时取消订阅SharedFlow

基础概念

SharedFlow 是 Kotlin 协程库中的一种热流(hot flow),它类似于 RxJava 中的 SubjectSharedFlow 可以在多个协程之间共享数据流,并且可以配置缓冲区大小、重放策略等。

相关优势

  1. 热流特性SharedFlow 是热流,即使没有订阅者,它也会继续发射数据。
  2. 缓冲区:可以配置缓冲区大小,处理数据生产者和消费者速度不匹配的情况。
  3. 重放策略:可以配置重放策略,使得新订阅者能够接收到之前发射的数据。
  4. 取消订阅:可以方便地取消订阅,避免资源浪费。

类型

SharedFlow 有多种类型,可以通过构造函数参数进行配置,例如:

  • replay:重放策略,指定新订阅者可以接收到多少个之前发射的数据。
  • extraBufferCapacity:额外缓冲区容量,用于处理突发数据。

应用场景

SharedFlow 适用于需要在多个协程之间共享数据的场景,例如:

  • 实时数据更新通知
  • 状态管理
  • 事件总线

取消订阅

当片段(Fragment)不可见时,取消订阅 SharedFlow 可以避免不必要的资源消耗和内存泄漏。可以通过以下步骤实现:

  1. 创建 SharedFlow
  2. 创建 SharedFlow
  3. 在协程中订阅 SharedFlow
  4. 在协程中订阅 SharedFlow
  5. 在片段不可见时取消订阅
  6. 在片段不可见时取消订阅

遇到的问题及解决方法

问题:当片段不可见时,仍然会接收到 SharedFlow 的数据。

原因:可能是因为没有正确取消订阅 SharedFlow,导致协程仍在运行。

解决方法:确保在片段不可见时取消订阅 SharedFlow。可以通过 lifecycleScope.coroutineContext.cancelChildren() 来取消所有子协程。

示例代码

代码语言:txt
复制
class MyFragment : Fragment() {

    private val sharedFlow = MutableSharedFlow<Int>()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        lifecycleScope.launch {
            sharedFlow.collect { value ->
                // 处理数据
                Log.d("MyFragment", "Received value: $value")
            }
        }
    }

    override fun onPause() {
        super.onPause()
        lifecycleScope.coroutineContext.cancelChildren()
    }

    private fun emitData() {
        lifecycleScope.launch {
            sharedFlow.emit(1)
        }
    }
}

参考链接

通过以上步骤和示例代码,可以确保在片段不可见时取消订阅 SharedFlow,避免不必要的资源消耗和内存泄漏。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

有小伙伴说看不懂 LiveData、Flow、Channel,跟我走

冷流只有在订阅者 collect 数据时,才按需执行发射数据流的代码。冷流和订阅者是一对一的关系,多个订阅者间的数据流是相互独立的,一旦订阅者停止监听或者生产代码结束,数据流就自动关闭。...热流和订阅者是一对多的关系,多个订阅者可以共享同一个数据流。当一个订阅者停止监听时,数据流不会自动关闭(除非使用 WhileSubscribed 策略,这个在下文再说)。 ---- 3....普通 Flow(冷流) 普通 Flow 是冷流,数据是不共享的,也没有缓存机制。数据源会延迟到消费者开始监听时才生产数据(如终端操作 collect{}),并且每次订阅都会创建一个全新的数据流。...lifecycleScope 的生命周期高于 STARTED 状态时,启动一个新的协程并执行代码块 // 当 lifecycleScope 的生命周期低于 STARTED 状态时,取消该协程...可以看到,这些协程 API 只有在最后组件 / 视图销毁时才会取消协程,当视图进入后台时协程并不会被取消,Flow 会持续生产数据,并且会触发更新视图。

2.5K10

Kotlin上的反应式流-SharedFlow和StateFlow

这个SharedFlow有三个事件和两个订阅者。第一个事件是在还没有订阅者的情况下发出的,所以它将永远丢失。 当SharedFlow发出第二个事件时,它已经有了一个订阅者,这个订阅者得到了上述事件。...当这种情况发生时,SharedFlow有两种选择,它要么缓冲该事件,并在恢复时将其发射给suspend的订阅者,要么在没有足够的缓冲区留给该事件时造成缓冲区溢出。...当订阅者恢复时,Flow也会恢复,将事件传递给所有订阅者并继续其工作。...当流最终到达第三个事件时,两个订阅者都得到了它的副本。 SharedFlow缓冲了这第三个事件,同时抛弃了之前的事件。后来,当第三个订阅者出现时,它也得到了第三个事件的副本。...这样,只有当生命周期至少处于STARTED状态时,coroutine才会启动,当它至少处于STOPPED状态时才会暂停,并在协程作用域取消时而取消。

2.3K60
  • Kotlin 学习笔记(六)—— Flow 数据流学习实践指北(二)StateFlow 与 SharedFlow

    SharedFlow 先来看看 SharedFlow,它是一个 subscriber 订阅者的角色,当一个 SharedFlow 调用了 collect 方法后,它就不会正常地结束完成;但可以 cancel...掉 collect 所在的协程,这样就可以取消掉订阅了。...SharedFlow 在每次 emit 时都会去 check 一下所在协程是否已经取消。...这是因为在第二个订阅者开始订阅时,数据已经都发射完了,而 SharedFlow 的重播 replay 为 2,就可将最近发射的两个数据再依次发送一遍,这就可以收到 2 和 3 了。...当 View 进入 STOPPED 状态时,LiveData.observe() 会自动取消注册使用方,这样就不会再接收到数据了,也符合常理。

    1.5K50

    谁能取代Android的LiveData- StateFlow or SharedFlow?

    当关闭时,它就会删除监听器,并且流量被取消。...对于开始参数,我们可以使用SharingStarted.WhileSubscribed(),这使得我们的Flow只有在订阅者的数量从0变成1时才开始共享(具体化),而当订阅者的数量从1变成0时就停止共享...时,该循环程序将在onStop()时暂停,并在onStart()时恢复,但它仍将被订阅到该流。...为了利用SharingStarted.WhileSubscribed()的力量,我们需要在onStop()上实际取消订阅,并在onStart()上再次订阅。这意味着取消收集的循环程序并重新创建它。...状态流总是有一个初始值,向新的订阅者复制一个最新的值,不缓冲任何更多的值,但保留最后发出的一个值,并且不支持 resetReplayCache。

    1.6K20

    解决Android开发中的痛点问题用Kotlin Flow

    Kotlin Flow是基于kotlin协程的一套异步数据流框架,可以用于异步返回多个值。...项目由MVP过渡到MVVM时,其中一个典型的重构手段就是将Presenter中的回调写法改写成在ViewModel中持有LiveData由View层订阅,比如以下场景: 在大力自习室中,当老师切换至互动模式时...也可以使用repeatOnLifecycle(State) 来在UI层收集,当生命周期 时,会取消协程,恢复时再重新启动协程。...所以考虑到存在订阅者协程被取消时发送事件的情况,即存在Channel处在无订阅者时的空档期收到事件情况。...只有当至少有一个订阅者时,onBufferOverflow才会生效。当无订阅者时,只有最近replay数目的值会保存,并且onBufferOverflow无效。

    3.3K20

    从 LiveData 迁移到 Kotlin 数据流

    _myUiState.value = result } } } StateFlow 是 SharedFlow 的一个比较特殊的变种,而 SharedFlow 又是 Kotlin...它允许被多个观察者共用 (因此是共享的数据流)。 它永远只会把最新的值重现给订阅者,这与活跃观察者的数量是无关的。 当暴露 UI 的状态给视图时,应该使用 StateFlow。...状态流的初始值 当使用 [SharingStarted.WhileSubscribed] 并带有 `replayExpirationMillis` 参数重置状态流时,也会用到 initialValue...started 接受以下的三个值: Lazily: 当首个订阅者出现时开始,在 scope 指定的作用域被结束时终止。 Eagerly: 立即开始,而在 scope 指定的作用域被结束时终止。...订阅将被重启,新数据会填充进来,当数据可用时更新视图。

    1.4K20

    Android SingleLiveEvent Redux with Kotlin Flow

    viewLifecycleOwner.lifecycleScope的文档指出,当生命周期被销毁时,这个Scope会被取消。这意味着有可能在生命周期达到停止状态但尚未销毁的情况下收到事件。...❝launchWhenX函数在生命周期离开期望状态时不会被取消。它们只是被暂停了。只有当生命周期达到DESTROYED状态时才会取消。...当生命周期被破坏时,作用域仍然会被取消,但是我们可以将观察者处于Activity状态的时间紧缩到只有启动和停止之间的生命周期状态。...-2d69f2bd6fa5 他创建了一组扩展函数,当一个生命周期的所有者达到开始时,自动订阅一个流量Collect器,当生命周期达到停止阶段时,取消Collect器。...视图(即Fragment或Activity)只有在生命周期达到开始状态后才观察该流。当生命周期到达停止的事件时,观察就被取消了。这允许安全地处理事件,而不用担心Android生命周期带来的困难。

    1K30

    快速进阶 Kotlin Flow:掌握异步开发技巧

    Flow 利用了这一特性来实现数据流的处理。 在 Flow 内部,数据流被建模为一系列的悬挂函数调用。每次发射数据时,发射器会暂停并将数据传递给订阅者。而订阅者在收集数据时会挂起,并等待数据传递。...冷流 冷流是指每个订阅者都有自己的数据流。在冷流模式下,每当有新的订阅者订阅数据流时,数据流的发射过程会重新开始。订阅者之间不会共享数据。...请注意,由于 Kotlin Flow 本身是冷流,要实现真正的热流,你需要使用 SharedFlow 或类似的技术。...Buffer(缓冲) buffer 策略会在数据流中使用一个缓冲区来存储数据,当数据产生速率超过消费速率时,数据会暂时存储在缓冲区中,直到有足够的空间将其传递给订阅者。...} } 结合取消和资源清理 当取消操作和资源清理同时存在时,你可以将它们结合起来,以确保在取消操作发生时进行资源清理。

    1.3K30

    (StateFlow & ShareFlow) VS (Flow & LiveData)来看业务适合哪个?

    一定要注意取消这个词和挂起的区别,挂起其实还是有订阅关系的当flow发射时还是会收到走collect上游并没有取消,但是取消就是协程作用域的取消collect函数不会执行了。...但是我们可以使用repeatOnLifecycle,它当离开某个生命周期的时候进行取消,符合的时候在开启一个新协程(也即会重新执行collect函数是新的订阅者)。...(超出该作用域时flow下游逻辑取消)repeatOnLifecycle针对生命周期取消订阅流的收集(上游)collect函数(符合在开启新协程重新订阅),WhileSubscribed策略配置订阅者超时时间进行取消...1.WhileSubscribed()当存在活跃订阅者(观察flow的协程域没有被取消)时flow函数也会活跃(执行flow函数),可配置最后一个订阅者取消订阅的超时时间进行取消flow函数运行也可以配置数据过期时间...(只有当订阅时才会运行)并且都在externalScope作用域取消时取消收集。

    74540

    (StateFlow & ShareFlow) VS (Flow & LiveData)

    一定要注意取消这个词和挂起的区别,挂起其实还是有订阅关系的当flow发射时还是会收到走collect上游并没有取消,但是取消就是协程作用域的取消collect函数不会执行了。...但是我们可以使用repeatOnLifecycle,它当离开某个生命周期的时候进行取消,符合的时候在开启一个新协程(也即会重新执行collect函数是新的订阅者)。...(超出该作用域时flow下游逻辑取消) repeatOnLifecycle针对生命周期取消订阅流的收集(上游)collect函数(符合在开启新协程重新订阅),WhileSubscribed策略配置订阅者超时时间进行取消...1.WhileSubscribed()当存在活跃订阅者(观察flow的协程域没有被取消)时flow函数也会活跃(执行flow函数),可配置最后一个订阅者取消订阅的超时时间进行取消flow函数运行也可以配置数据过期时间...(只有当订阅时才会运行)并且都在externalScope作用域取消时取消收集。

    1K40

    Kotlin 学习笔记(七)—— Flow 数据流学习实践指北(三)冷流转热流以及代码实例

    3. shareIn 与 stateIn 使用指北 3.1 SharingStarted.WhileSubscribed() 实际使用 从上面的介绍可知,这种启动方式可以在没有消费者时自动取消上游数据流...,做一些自己的操作;当所有消费者都停止收集时,再处理另外的一些操作,比如资源回收等。...,当原流依次发出 a、b 两值时,新流都会接收,但如果新流 a 值的相关操作还未结束,则会取消 a 值的相关操作,并用 b 值进行操作。...当输入的新字符串到来时,就会将之前旧字符串还未结束的请求操作取消掉,用新的字符串去请求数据。...参考文献 StateFlow 和 SharedFlow 官方文档 https://developer.android.google.cn/kotlin/flow/stateflow-and-sharedflow

    1.4K40

    flows channels 傻傻分不清

    当你开始在异步数据流的基础上构建你的应用架构时,自然会出现对转换的需求,而Channel成本也开始累积。 Kotlin Flow的简单设计允许有效地实现转换操作。...关于 "cold flow,hot channel "的故事描述了Kotlin flow背后的原因,并展示了它们比Channel更适合的使用情况--返回按需计算的异步值流。...一个shared flow的所有订阅者都在自己的上下文中异步地收集事件。发射器并不等待,直到订阅者完成对事件的处理。然而,当shared flow的缓冲区满了,发射器会暂停,直到缓冲区有空间。...它的最近值总是可用的,事实上,最近的值是唯一重要的,所以更新它总是可以不暂停的。 有了状态流,复杂Channel和简单流之间的性能差异变得非常明显。...请注意,有Channel的SingleShotEventBus实现只在没有取消的情况下对每个发布的事件精确地处理一次。当流的订阅者被取消时,事件可能无法被传递。

    49810

    Kotlin就几行代码? 用SharedFlow写个FlowEventBus

    现在SharedFlow稳定了,那是不是也能搞一波?...于是有了FlowEventBus 常用消息总线对比 image.png 设计构思 通过学习 从 LiveData 迁移到 Kotlin 数据流  得到思路: SharedFlow作为事件载体 : 优点...: 依托协程轻松切换线程 可以通过replay实现粘性效果 可以被多个观察者订阅 无观察者自动清除事件不会造成积压 结合 Lifecycle 感知生命周期,做到响应时机可控 。...依赖库版本 关键在于 kotlinx-coroutines > 1.4.x  和 lifecycle-runtime-ktx > 2.3.x API 以下示例中的Event均是随意定义的类,只是测试时为了区分事件而定义的名字...协程的SharedFlow和Lifecycle 因此实现起来非常简单。

    1K10

    SharedFlow vs StateFlow,一篇看懂选择和使用技巧

    SharedFlow 使用了一种基于事件溯源的机制,当有新的事件产生时,将事件添加到共享的事件序列中,然后通知所有订阅者。...当观察者订阅时,它只是加入了已经运行的数据流,开始接收当前已经产生的事件。 冷流是一种被动的数据流。它在有观察者订阅时才开始发射事件。每个观察者都会获得相同的事件序列,而不会受到其他观察者的影响。....*/ } replay: 表示在订阅时从流中回放的元素数量。默认值为 0,表示不回放任何元素。如果设置为正整数 n,则在订阅时将向新订阅者回放最近的 n 个元素。...onBufferOverflow: 表示在缓冲区溢出时的处理策略。默认值为 BufferOverflow.SUSPEND,表示当缓冲区溢出时暂停发射,等待订阅者消费。...当有新的聊天消息时,通过 sendChatMessage 方法更新 SharedFlow,所有订阅者都能获取到最近的数据序列。

    1.8K10

    Flow 操作符 shareIn 和 stateIn 使用须知

    而这不是 SharedFlow 的使用方式。 提升性能 通过共享所有收集者要观察的同一数据流实例 (而不是按需创建同一个数据流的新实例),这些 API 可以为我们提升性能。...locationDataSource.locationsSource.shareIn(externalScope, WhileSubscribed()) } WhileSubscribed 共享策略用于在没有收集者时取消上游数据流...在大部分情况下,您可以使用 **WhileSubscribed(5000)**,当最后一个收集者消失后再保持上游数据流活跃状态 5 秒钟。这样在某些特定情况 (如配置改变) 下可以避免重启上游数据流。...这样会在每次函数调用时创建一个新的 SharedFlow 或 StateFlow,而它们将会一直保持在内存中,直到作用域被取消或者在没有任何引用时被垃圾回收。...如果答案是肯定的,您可能需要为 SharedFlow 或 StateFlow 实例创建一个 map,并在 subscriptionCount 为 0 时移除引用并退出上游数据流。

    4.7K20

    Flow简介

    Kotlin 协程中使用挂起函数可以实现非阻塞地执行任务并将结果返回回来,但是只能返回一个计算结果。...当有多个订阅者的时候,每个订阅者都会收到发送者完整的流程。即订阅者和发送者都是一对一的关系。...collect{ delay(1000) Log.e(TAG, it.toString()) } 上面三个按钮的代码都贴上去了,其中订阅者1和订阅者2代码一样,当我们只是点发送者按钮时,...热流 热流是共享的,有缓存的,不管订阅者是否存在,只要发送了事件就会被消费,热流和订阅者是一对多的关系,多个订阅者可以共享同一个数据流。当一个订阅者停止监听时,数据流不会自动关闭。...,因为在订阅之前已经被消费了,所以收不到数据 热流的具体实现SharedFlow和StateFlow,分别对应的实现类MutableSharedFlow和是MutableStateFlow,所以我们要讲的也就是这两个类

    97510

    使用协程和 Flow 简化 API 设计

    如果您是库作者,您也许希望用户在使用 Kotlin 协程与 Flow 时可以更加轻松地调用您基于 Java 或回调的 API。...当逻辑变得复杂时,这些回调容易使代码变得不可读,而我们可以使用协程来摆脱它们。 如果您希望探索其它解决方案,可以通过上面函数所链接的源代码为您带来启发。...流数据 如果我们转而希望用户的设备在真实的环境中移动时,周期性地接收位置更新 (使用 requestLocationUpdates 函数),我们就需要使用 Flow 来创建数据流。...通常情况下,使用 callbackFlow 构建流适配器遵循以下三个步骤: 创建使用 offer 向 flow 添加元素的回调; 注册回调; 等待消费者取消协程,并注销回调。...( // 让 flow 跟随 applicationScope applicationScope, // 向新的收集器发送上一次发送的元素 replay = 1, // 在有活跃的订阅者时

    1.6K20

    LiveData 还有学习的必要吗?—— Jetpack 系列(2)

    2、Kotlin Flow: Kotlin Flow 是基于 Kotlin 协程基础能力搭建的一套数据流框架,从功能复杂性上看是介于 LiveData 和 RxJava 之间的解决方案。...并且在 Kotlin 协程的加持下,Kotlin Flow 目前是 Google 主推的数据流框架。...而观察者的持有的初始版本号是 -1,因此当注册新观察者并且正好宿主的生命周期是大于等于可见状态(STARTED)时,就会尝试分发数据,这就是数据重放。...这样的话,当观察者收到重放的数据时,由于其中的标记位已经显示被消费,因此会抛弃该事件。...Flow Google 对 Flow 的定位是 Kotlin 环境下对 LiveData 的替代品,使用 SharedFlow 可以控制重放数量,可以设置为 0 表示禁止重放。

    3.6K10

    实战 | 使用 Kotlin Flow 构建数据流 管道

    假设我们处于 UserMessagesDataSource 中,当您希望频繁地在应用内检查新消息时,可以将用户消息暴露为消息列表类型的数据流。...如果您调用 repeatOnLifecycle 并传入 STARTED 状态,界面就只会在屏幕上显示时收集数据流发出的信号,并且在应用转到后台时取消收集。...在旋转场景中我们不希望重启任何数据流以便尽可能快地完成过渡,而在回到主屏幕的场景中我们则希望停止所有数据流以便节省电量和其他资源。...我们可以通过设置超时时间来正确判断不同的场景,当停止收集 StateFlow时,不会立即停止所有上游数据流,而是会等待一段时间,如果在超时前再次收集数据则不会取消上游数据流,这就是 WhileSubscribed...SharedFlow 的更多详细信息,请参阅: StateFlow 和 SharedFlow。

    1.5K10
    领券