【问题标题】:Retrieving latest value of a Flow which is not a StateFlow检索不是 StateFlow 的 Flow 的最新值
【发布时间】:2022-11-10 12:55:26
【问题描述】:

如何获得Flow 的最新值?我没有需要最新值的StateFlow。这是浓缩的场景:

有一个暴露 StateFlow 的存储库

val repositoryExposedStateFlow: StateFlow<SomeType> = MutableStateFlow(...)

此外,还有映射器转换 StateFlow 之类的

val mappedFlow: Flow<SomeOtherType> = repositoryExposedStateFlow.flatMapLatest { ... }

mappedFlow 不再是 StateFlow,而只是 Flow。因此,当有StateFlow 时,我无法获得最新/当前值。

无论如何,我在某个时候需要Flow 的最新值。由于这一点不在ViewModel 中,而是在一些用例实现中,我不能简单地执行stateIn 并在ViewModel 中一直保持最新值ViewModel 还活着——否则我不得不将价值传递给所有用例。实际上,在一个用例中,我触发了网络刷新,这会导致在StateFlowmappedFlow 上发出新值。

在用例中我有CoroutineScopes。所以我想出了

suspend fun <T> Flow<T>.getState(): T {
    return coroutineScope {
        val result = stateIn(
            scope = this
        ).value
        coroutineContext.cancelChildren()

        result
    }
}

如果不使用coroutineContext.cancelChildren(),该方法将永远不会返回,因为coroutineScope 会阻塞调用者,直到所有子协程完成。由于stateIn 永远不会完成,我手动取消所有孩子。

显然这是一件坏事。

但是我怎样才能更好地解决这个问题呢?在我看来,问题出在StateFlow 映射导致常规Flow 实例。

【问题讨论】:

  • “如何获取 Flow 的最新值?” - 你没有,除非你自己在某个地方缓存它。 “我在某个时候需要那个流中的最新值”——也许解决方案是重新审视这个假设。
  • 是的,感觉就像我在另一个地方做错了什么。请参阅与@Tenfour04 的讨论,我们正在尝试找出答案。

标签: android kotlin kotlin-flow stateflow


【解决方案1】:

是的,您只需在流程中拨打first()。由于它由上游 StateFlow 支持,first() 调用将获取该支持 StateFlow 的当前值,通过下游操作员发生的任何转换运行它,并返回该值。

这有效地使您获得与上述尝试相同的结果。

缺点是必须运行所有下游运算符,因此可能很昂贵。

这只有在存在上游 StateFlow 时才有可能。否则,没有可供您检索的最新值的概念。

不过,我会挑战您获得最新价值的需求。通常,您收集流,因此您已经在使用当前值。流旨在用于反应式编程。

【讨论】:

  • 感谢您指出first()!回到你的挑战:一方面我想在 UI 中显示repositoryExposedStateFlow 的最新状态,所以我需要一个响应式构造。另一方面,在调用 UI 操作时,我触发了一些网络请求,这将导致在 repositoryExposedStateFlow 上发出新数据,但在此 UI 操作中,我需要等到新数据到达 Flow 中。
  • 我能想到的唯一其他方法是终止该 UI 操作并存储一些与即将更新的 repositoryExposedStateFlow 相结合的状态。对我来说似乎有些矫枉过正,所以我正在寻找替代方案。 -- 希望我能很好地解释我的情况。
  • 我不确定我是否理解。 “但在这个 UI 操作中,我需要等到新数据到达 Flow 中”听起来也很被动。但是如果真的没有办法,我不明白你为什么不在下游流上使用stateIn。如果你想要最新的状态,这是保持它的最简单方法,所以它不会矫枉过正。
  • 可能我将不得不创建一个示例项目,否则可能很难深入了解事物。将发布一个回购链接:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-19
  • 2023-02-26
  • 1970-01-01
  • 1970-01-01
  • 2021-01-06
  • 1970-01-01
相关资源
最近更新 更多