【问题标题】:Why doesn't two collect function not work in the same suspended function?为什么两个收集功能不能在同一个挂起功能中工作?
【发布时间】:2021-02-26 00:06:34
【问题描述】:

具有两个数据源(本地和远程)的存储库,我请求在初始化时从两个源获取 accessToken。来自本地和远程的函数都返回一个我试图在初始化中收集的流。但只有第一个收集成功运行,而另一个则没有。这是为什么?有没有一种干净的方式来处理这种用例?

    private suspend fun init() {
        refreshAccessTokenFromLocal()
        refreshAccessTokenFromNetwork()
    }
    
    private suspend fun refreshAccessTokenFromNetwork() {
        networkDataSource.refreshAccessToken()
            .collect { accessToken ->
                Timber.d("Debug: refreshing accessToken from network $accessToken")
                localDataSource.updateAccessToken(accessToken)
            }
    }

    private suspend fun refreshAccessTokenFromLocal() {
        localDataSource.getAccessToken().collect { accessToken ->
            Timber.d("Debug: refreshing accessToken from local $accessToken")
            accessTokenAsStateFlow.value = accessToken
        }
    }

【问题讨论】:

  • 可能是 Flow 实现。第一个 Flow 完成了吗?在取消之前,流可以设计为有限或无限的。如果你只想要一个 Flow 中的一个值,你可以使用first() 而不是 collect(),然后如果 Flow 是无限的,它就不会永远运行。

标签: kotlin kotlin-coroutines


【解决方案1】:

collect() 函数不会在后台启动任何东西。它“阻塞”当前协程,直到流程完成。这就是为什么您只会看到正在收集的第一个流。

如果您只想从每个流中获取一个值并使用它,您可以在每个流上调用first()。但是,这可能不是最佳选择,因为您将按顺序执行操作。

你也可以这样做:

coroutineScope {
    val fromNetwork = async { networkDataSource.refreshAccessToken().first() }
    val fromLocal = async { localDataSource.getAccessToken().first() }

    localDataSource.updateAccessToken(fromNetwork.await())
    accessTokenAsStateFlow.value = fromLocal.await()
}

【讨论】:

    猜你喜欢
    • 2021-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多