首页 > 解决方案 > 为什么两个收集功能不能在同一个挂起功能中工作?

问题描述

具有两个数据源(本地和远程)的存储库,我请求在初始化时从两个源中获取 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
        }
    }

标签: kotlinkotlin-coroutines

解决方案


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

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

你也可以这样做:

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

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

推荐阅读