如何获取协程外Flow的值?

新手上路,请多包涵

如何像 LiveData 一样在协程外获取 Flow 的值?

 // Suspend function 'first' should be called only from a coroutine or another suspend function
flowOf(1).first()

 // value is null
flowOf(1).asLiveData().value

 // works
MutableLiveData(1).value

语境

我在存储库层中避免 LiveData 以支持 Flow 。然而,我需要设置、观察和收集立即消费的价值。后者对于 OkHttp3 Interceptor 中的身份验证目的很有用。

原文由 maxbeaudoin 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 940
2 个回答

好吧…您正在寻找的并不是 Flow 的真正用途。 Flow 只是一个流。它不是价值持有者,因此您无法检索任何东西。

因此,根据拦截器的需要,有两种主要途径。

也许您的拦截器可以在没有来自存储库的数据的情况下生存。 IOW,如果数据存在,您将使用它,否则拦截器可以继续。在这种情况下,您可以让您的存储库发出流,但也可以维护您的拦截器可以使用的“当前值”缓存。这可能是通过:

  • BroadcastChannel
  • LiveData
  • 您在内部更新并公开为 val 的存储库中的一个简单属性

但是,如果您的拦截器需要数据,那么这些都不会直接起作用,因为如果数据尚未准备好,它们都会导致拦截器获取 null 。您需要的是一个 可以 阻塞的调用,但如果数据通过某种形式的缓存准备就绪,则可能会快速评估。根据存储库的实现以及首先提供 Flow 的内容,其细节会有很大差异。

原文由 CommonsWare 发布,翻译遵循 CC BY-SA 4.0 许可协议

你可以这样做

val flowValue: SomeType
runBlocking(Dispatchers.IO) {
    flowValue = myFlow.first()
}

是的,它不完全是 Flow 的用途。

但是并不总是可以使所有事情都异步,就此而言,甚至不可能总是“只制作一个同步方法”。例如,当前的 Datastore 版本(应该取代 Android 上的共享首选项)只公开 Flow 而没有其他内容。这意味着您很容易陷入这种情况,因为 Activity 或 Fragments 的生命周期方法都不是协程。

如果你能帮助它,你应该总是从挂起函数调用协程并避免进行 runBlocking 调用。很多时候它是这样工作的。但这并不是一种万无一失的方法。您可以使用 runBlocking 引入死锁。

原文由 Max 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题