问题标签 [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.

0 投票
1 回答
264 浏览

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 似乎也不起作用,我不知道为什么

0 投票
0 回答
48 浏览

android - 在 viewModelScope 中抛出异常,但在它之外捕获它

所以我得到了一个 SharedFlow ,它在某些情况下会发出一些东西。在另一点上,我得到了一个 try-catch 块,并且只有当 Flow 在执行时收集到一些东西时,我才想跳过对 try 块的进一步执行。同时我不想在收集时阻塞线程。如果没有发出任何内容,我希望 try 块正常执行。所以这是我的第一个想法:

使用这个,如果 execption 被抛出,应用程序会崩溃,它不会被捕获。从我在寻找解决方案时阅读的内容来看,您似乎只能在同一个协程中捕获异常。但是这样做不会让我在 viewModelScope 之后跳过进一步的执行。我尝试了很多东西,但最后,我总是以

  1. 在内部捕获异常并且不跳过进一步的执行
  2. 等待一个如果没有发出就永远不会到达的结果,阻止进一步的执行
  3. 未捕获异常,导致应用程序崩溃

非常欢迎针对此问题的任何想法,输入或替代解决方案,在此先感谢。

0 投票
0 回答
291 浏览

android - 片段恢复时如何避免repeatOnLifecycle一次又一次地执行

导航回片段时,如何避免再次执行 collect{} 代码。

视图模型类

当我首先更改 viewModel 中的 _commitResult 值时,跳转到另一个片段工作正常。不幸的是,当我回到片段时。collect{ // navigate to another fragment}将再次执行。

我知道什么时候回到片段。onCreateView 再次执行,viewModel 将在之前发出数据存储,所以collect { // navigate to another fragment}执行。我怎样才能避免这种情况?

与 LiveData 相同,我使用 Event 通过 LiveData 解决此问题。

我怎样才能用状态流处理这个?实际上我不喜欢 Event<.> 来处理这个,我是否以错误的方式使用状态流?我该如何解决这个问题?如果有人可以提供帮助,请提前致谢。

0 投票
1 回答
23 浏览

android - 如何避免 FragmentManager 中的竞争条件?

我的目标是在片段堆栈中只允许同一对话框片段的一个实例。

当前触发条件来自 SharedFlow 并且可以7ms在值之间多次触发。

这是我尝试过的:

  1. 将代码放在一个synchronized块中
  2. 通过调用检查现有片段是否在堆栈中fm.findFragmentByTag

但是,这两个条件都不足以防止fragment多次添加到fragmentManager。

我试过了,dialogFragment.showNow(fm, tag)但它不稳定而且崩溃了

感谢任何帮助。

0 投票
1 回答
242 浏览

android - SharedFlow 不会在片段(收集)处向订阅者发出值

我想使用SharedFlow而不是StateFlow因为第一个不需要初始值

视图模型

片段

我只是第一次尝试使用它,所以我不完全理解它是如何工作的。

如果我替换shareInstateIn并设置null为初始值(第三个参数),它工作正常,但是在collect回调中我需要检查它是否不是null在提交PagingData给适配器之前

更新

似乎如果在开始收集 SharedFlow 之前发出值,那么新订阅者将不会收到最新值

所以我需要更改shareIn(viewModelScope, SharingStarted.Eagerly)

或者

让它发挥作用

但是哪一个更好呢?我只需要保留相同的单个实例PagingData

0 投票
0 回答
86 浏览

android - 安卓。SharedFlow 用于更新状态

是否可以订阅来自不同活动的 SharedFlow 状态更改。例如,我有 Activity A 和 Activity B。在 Activity BI 内部需要获取一些数据,当我返回 Activity A 时,屏幕需要由 Activity B 的数据更新。也就是说,当请求接收数据发送到Activity B,我可以在请求完成之前返回上一屏,此时加载状态应该会显示在上一屏(Activity A)上。当接收到数据时,它们应该显示在活动 A 中。为此,我想使用带有 SharedFlow 的通用单例存储库。在活动B中,我会向repository请求数据,此时状态会更新,一旦收到数据,就会出现在活动A中。是否可以使用共享流来实现。

0 投票
1 回答
57 浏览

android - SharedFlow中大量的extraBufferCapacity会导致内存泄漏吗?

我正在开发一个具有 MVVM 架构的聊天应用程序,我SharedFlow用来将传入的消息RepositoryViewModel. 当用户离线,另一个用户向他发送大量消息时,用户一上线,消息就会接踵而至,Repository需要传送到ViewModel用户界面中显示。我首先将extraBufferCapacity值设置为 1,然后看到在这种情况下,只有前两条消息在ViewModel. 然后我将extraBufferCapacity值增加到 6 并看到前 7 条消息被传输到ViewModel. 现在如果我将extraBufferCapacity值增加到Int.MAX_VALUE,会导致内存泄漏吗?

存储库:

视图模型:

0 投票
1 回答
27 浏览

android - SharedFlow.last() 永远不会返回

我有一个重播值为 1 的 sharedFlow。但是当我试图访问最后一个发出的值时,调用永远不会返回(虽然first()会)。

下面是我的代码:

getGame()回调流在哪里:

所以这个:val myGame = game.last()从不返回任何东西val myGame = game.first()

为什么和如何?

0 投票
1 回答
30 浏览

android - 在 Jetpack Compose 中重新创建活动/配置更改后,如何从 SharedFlow 获取先前的值?

假设我ScanActivity使用可以扫描条形码的 jetpack compose,结果将显示在TextField并且结果将在配置更改(例如屏幕旋转)后保留下来。我不会使用StateFlow,因为在显示结果之后我旋转我的屏幕它会再次调用 API,但结果变为空我想保留结果。

扫描活动:

扫描视图模型:

我的文本字段:

0 投票
1 回答
55 浏览

android - Flow 多次收集时会发出不同的值

我创建了一个从中发出数据的流。当我两次收集此流时,从同一个变量发出了 2 组不同的数据,而不是向两个收集器发出相同的值。

我有一个我自己创建的简单流程。文本将每秒记录两次

在我的 viewModel 中,我有一个简单的函数可以获取上一个 Flow

在我的 Fragment 中,我收集并显示我的 Flow

如果我将 Flow 转换为 StateFlow 或 SharedFlow,我不再有这个问题。我不明白为什么会发生这种情况,因为我使用的是相同的“demoFlow”变量。有没有办法在不转换为 StateFlow 或 SharedFlow 的情况下从“demoFlow”获取相同的值?