问题标签 [kotlin-sharedflow]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
android - 您如何让订阅者订阅 kotlin sharedflow 并行运行操作?
我连接到每 250 毫秒发送一次数据的蓝牙设备
在我的视图模型中,我希望订阅所述数据,运行一些暂停代码(运行大约需要 1000 毫秒),然后显示结果。
以下是我正在尝试做的一个简单示例
存储库:
视图模型
如您所见,当数据到来时,首先我验证它以确保它没有损坏(在默认调度程序上)然后我对其执行一些操作(保存并运行一个需要时间在 IO 调度程序上的长算法)然后我改变它以便应用程序用户可以理解它(切换回默认调度程序)然后我将其发布到可变实时数据,因此如果有来自 ui 层的订阅者,他们可以看到当前数据(在主调度程序上)
我有两个问题
a) 如果validateData
失败,我该如何取消当前发射并继续下一个发射?
b) 有没有办法让在 viewModel 上工作的 dataFlow 订阅者生成新线程,以便延迟部分可以并行运行?
有没有办法做到这一点?
我尝试使用 buffer(),正如文档所述,“通过指定容量的通道缓冲流量排放并在单独的协程中运行收集器”。但是当我将它设置为 BufferOverflow.SUSPEND 我得到第一部分的行为,当我将它设置为 BufferOverflow.DROP_OLDEST 或 BufferOverflow.DORP_LATEST 我失去了排放
我也尝试过像这样使用 .conflate() :
即使排放一个接一个地开始,有延迟的部分仍然等待前一个完成,然后再开始下一个
当我对那部分使用 .flowOn(Dispatchers.Default) 时,我会释放排放,当我使用 .flowOn(Dispatchers.IO) 或类似的东西时,Executors.newFixedThreadPool(4).asCoroutineDispatcher()
他们总是等待前一个完成后再开始新的
编辑2:
经过大约 3 小时的实验,这似乎有效
但是我仍然没有弄清楚如果验证数据失败如何取消发射
并且由于某种原因,它仅在我使用 Dispatchers.IO 、 Executors.newFixedThreadPool(20).asCoroutineDispatcher() 和 Dispatchers.Unconfined 时才有效,我在注释 (A) 的位置, Dispatchers.Main 似乎不起作用(我预期的)但是Dispatchers.Default 似乎也不起作用,我不知道为什么
android - 在 viewModelScope 中抛出异常,但在它之外捕获它
所以我得到了一个 SharedFlow ,它在某些情况下会发出一些东西。在另一点上,我得到了一个 try-catch 块,并且只有当 Flow 在执行时收集到一些东西时,我才想跳过对 try 块的进一步执行。同时我不想在收集时阻塞线程。如果没有发出任何内容,我希望 try 块正常执行。所以这是我的第一个想法:
使用这个,如果 execption 被抛出,应用程序会崩溃,它不会被捕获。从我在寻找解决方案时阅读的内容来看,您似乎只能在同一个协程中捕获异常。但是这样做不会让我在 viewModelScope 之后跳过进一步的执行。我尝试了很多东西,但最后,我总是以
- 在内部捕获异常并且不跳过进一步的执行
- 等待一个如果没有发出就永远不会到达的结果,阻止进一步的执行
- 未捕获异常,导致应用程序崩溃
非常欢迎针对此问题的任何想法,输入或替代解决方案,在此先感谢。
android - 片段恢复时如何避免repeatOnLifecycle一次又一次地执行
导航回片段时,如何避免再次执行 collect{} 代码。
视图模型类
当我首先更改 viewModel 中的 _commitResult 值时,跳转到另一个片段工作正常。不幸的是,当我回到片段时。collect{ // navigate to another fragment}
将再次执行。
我知道什么时候回到片段。onCreateView 再次执行,viewModel 将在之前发出数据存储,所以collect { // navigate to another fragment}
执行。我怎样才能避免这种情况?
与 LiveData 相同,我使用 Event 通过 LiveData 解决此问题。
我怎样才能用状态流处理这个?实际上我不喜欢 Event<.> 来处理这个,我是否以错误的方式使用状态流?我该如何解决这个问题?如果有人可以提供帮助,请提前致谢。
android - 如何避免 FragmentManager 中的竞争条件?
我的目标是在片段堆栈中只允许同一对话框片段的一个实例。
当前触发条件来自 SharedFlow 并且可以7ms
在值之间多次触发。
这是我尝试过的:
- 将代码放在一个
synchronized
块中 - 通过调用检查现有片段是否在堆栈中
fm.findFragmentByTag
但是,这两个条件都不足以防止fragment多次添加到fragmentManager。
我试过了,dialogFragment.showNow(fm, tag)
但它不稳定而且崩溃了
感谢任何帮助。
android - SharedFlow 不会在片段(收集)处向订阅者发出值
我想使用SharedFlow
而不是StateFlow
因为第一个不需要初始值
视图模型:
片段:
我只是第一次尝试使用它,所以我不完全理解它是如何工作的。
如果我替换shareIn
为stateIn
并设置null
为初始值(第三个参数),它工作正常,但是在collect
回调中我需要检查它是否不是null
在提交PagingData
给适配器之前
更新
似乎如果在开始收集 SharedFlow 之前发出值,那么新订阅者将不会收到最新值
所以我需要更改shareIn(viewModelScope, SharingStarted.Eagerly)
为
或者
让它发挥作用
但是哪一个更好呢?我只需要保留相同的单个实例PagingData
android - 安卓。SharedFlow 用于更新状态
是否可以订阅来自不同活动的 SharedFlow 状态更改。例如,我有 Activity A 和 Activity B。在 Activity BI 内部需要获取一些数据,当我返回 Activity A 时,屏幕需要由 Activity B 的数据更新。也就是说,当请求接收数据发送到Activity B,我可以在请求完成之前返回上一屏,此时加载状态应该会显示在上一屏(Activity A)上。当接收到数据时,它们应该显示在活动 A 中。为此,我想使用带有 SharedFlow 的通用单例存储库。在活动B中,我会向repository请求数据,此时状态会更新,一旦收到数据,就会出现在活动A中。是否可以使用共享流来实现。
android - SharedFlow中大量的extraBufferCapacity会导致内存泄漏吗?
我正在开发一个具有 MVVM 架构的聊天应用程序,我SharedFlow
用来将传入的消息Repository
从ViewModel
. 当用户离线,另一个用户向他发送大量消息时,用户一上线,消息就会接踵而至,Repository
需要传送到ViewModel
用户界面中显示。我首先将extraBufferCapacity
值设置为 1,然后看到在这种情况下,只有前两条消息在ViewModel
. 然后我将extraBufferCapacity
值增加到 6 并看到前 7 条消息被传输到ViewModel
. 现在如果我将extraBufferCapacity
值增加到Int.MAX_VALUE
,会导致内存泄漏吗?
存储库:
视图模型:
android - SharedFlow.last() 永远不会返回
我有一个重播值为 1 的 sharedFlow。但是当我试图访问最后一个发出的值时,调用永远不会返回(虽然first()
会)。
下面是我的代码:
getGame()
回调流在哪里:
所以这个:val myGame = game.last()
从不返回任何东西val myGame = game.first()
。
为什么和如何?
android - 在 Jetpack Compose 中重新创建活动/配置更改后,如何从 SharedFlow 获取先前的值?
假设我ScanActivity
使用可以扫描条形码的 jetpack compose,结果将显示在TextField
并且结果将在配置更改(例如屏幕旋转)后保留下来。我不会使用StateFlow
,因为在显示结果之后我旋转我的屏幕它会再次调用 API,但结果变为空我想保留结果。
扫描活动:
扫描视图模型:
我的文本字段:
android - Flow 多次收集时会发出不同的值
我创建了一个从中发出数据的流。当我两次收集此流时,从同一个变量发出了 2 组不同的数据,而不是向两个收集器发出相同的值。
我有一个我自己创建的简单流程。文本将每秒记录两次
在我的 viewModel 中,我有一个简单的函数可以获取上一个 Flow
在我的 Fragment 中,我收集并显示我的 Flow
如果我将 Flow 转换为 StateFlow 或 SharedFlow,我不再有这个问题。我不明白为什么会发生这种情况,因为我使用的是相同的“demoFlow”变量。有没有办法在不转换为 StateFlow 或 SharedFlow 的情况下从“demoFlow”获取相同的值?