【问题标题】:Why does my Kotlin Flow onCompletion never run?为什么我的 Kotlin Flow onCompletion 从不运行?
【发布时间】:2021-06-29 11:34:51
【问题描述】:

所以我有一个流程,我需要它从缓存中发出一个值,但最后它会进行 API 调用以提取值,以防缓存中没有任何内容(或刷新它的值)。我正在尝试这个

override val data: Flow<List<Data>> = dataDao.getAllCachedData()
    .onCompletion {
        coroutineScope {
            launch {
                requestAndCacheDataOrEmitError()
            }
        }
    }
    .map { entities ->
        entities
            .map { it.toData() }
            .filter { it !is Data.Unknown }
    }
    .filterNotNull()
    .catch { emitRepositoryError(it) }

所以我们的想法是我们发出缓存,然后进行 API 调用以获取新数据,而不考虑原始映射。但我不希望它阻塞。例如,如果我们使用这个流程,我不希望调用函数被 onCompletion 阻塞。

我认为问题在于onCompletion 永远不会运行。我设置了一些断点/日志,但它根本不会运行,即使在 coroutineScope 之外。

【问题讨论】:

  • 只有当您取消正在收集它的协程时,来自 DAO 的流才会完成。您希望何时完成?就在流量的第一个值之后?你只关心第一个值吗?
  • 我明白了,我不知道它只会在取消时运行。我关心第一个值,但在某些情况下缓存中还没有数据,所以我希望 onCompletion 中的函数运行将更新缓存,并且流将发出一个新值。它应该在 onCompletion 运行后再次发射。我基本上希望这会发出两次。一次从缓存中提取,第二次在 onCompletion 完成后更新数据。

标签: kotlin kotlin-coroutines flow


【解决方案1】:

我不太了解您正在做的工作,但我认为当您在某个范围内收集流量时。您结束了流程将被放入 onCompletion 的范围

 var job : Job? = null
fun scan() {
    job =  viewModelScope.launch {
        bigfileManager.bigFile.collect {
            if (it is ResultOrProgress.Result) {
                _bigFiles.value = it.result ?: emptyList()
            } else {
                _updateProgress.value = (it as ResultOrProgress.Progress).progress ?: 0
            }

        }
    }
}

fun endScreen(){
    job?.cancel()
}

【讨论】:

    猜你喜欢
    • 2021-10-28
    • 2016-06-29
    • 2011-03-23
    • 2020-03-18
    • 1970-01-01
    • 1970-01-01
    • 2010-10-21
    • 1970-01-01
    • 2011-07-29
    相关资源
    最近更新 更多