繁体   English   中英

如何在协程之外获取 Flow 的值?

[英]How to get the value of a Flow outside a coroutine?

与 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中的身份验证目的。

你可以这样做

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

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

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

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

嗯...您正在寻找的并不是Flow的真正用途。 Flow只是一个 stream。 它不是价值持有者,因此您无法检索任何内容。

因此,根据您的拦截器需要,有两种主要途径可以降低 go。

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

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

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

您应该查看StateFlow ,您可以在其中访问该值。

https://developer.android.com/kotlin/flow/stateflow-and-sharedflow

你可以使用这样的东西:

    fun <T> SharedFlow<T>.getValueBlockedOrNull(): T? {
        var value: T?
        runBlocking(Dispatchers.Default) {
            value = when (this@getValueBlockedOrNull.replayCache.isEmpty()) {
                true -> null
                else -> this@getValueBlockedOrNull.firstOrNull()
            }
        }
        return value
    }

您可以使用MutableStateFlowMutableSharedFlow从协程发出数据并在Activity/Fragment中接收数据。 MutableStateFlow可用于 state 管理。 初始化时需要默认值。 MutableSharedFlow不需要任何默认值。

But, if you don't want to receive stream of data, (ie) your API call sends data only once, you can use suspend function inside coroutine scope and the function will perform the task and return the result like synchronous function call.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM