android 如何在应用程序最小化时暂停/停止收集/发射Flow中的数据?

xv8emn3q  于 2023-02-20  发布在  Android
关注(0)|答案(3)|浏览(355)

我有一个在循环中返回Flow的用例和远程存储库,我在ViewModel中收集用例的结果,如下所示:

viewModelScope.launch {
    useCase.updatePeriodically().collect { result ->
        when (result.status) {
            Result.Status.ERROR -> {
                errorModel.value = result.errorModel
            }
            Result.Status.SUCCESS -> {
                items.value = result.data
            }
            Result.Status.LOADING -> {
                loading.value = true
            }
        }
    }
}

问题是当应用程序在后台(最小化)流程继续工作。所以我可以暂停它时,应用程序在后台和恢复它时,应用程序回到前台?
我也不想在我的视图中观察数据(片段或活动)。

polhcujo

polhcujo1#

我将尝试使用stateIn操作符和当前在视图中使用流的方式。
比如:

val state = useCase.updatePeriodically().map { ... }
    .stateIn(viewModelScope, SharingStarted.WhileSubscribed, initialValue)

并从视图中使用它,例如:

viewModel.flowWithLifecycle(this, Lifecycle.State.STARTED)
            .onEach {
                
            }
            .launchIn(lifecycleScope)

有关如何从UI收集流的其他潜在方法:https://medium.com/androiddevelopers/a-safer-way-to-collect-flows-from-android-uis-23080b1f8bda

    • 编辑:**

如果您不想从视图中使用它,您仍然需要向虚拟机发出信号,表明您的视图当前处于后台。

private var job: Job? = null

fun start(){
    job = viewModelScope.launch {
        state.collect { ... }
    }
}

fun stop(){
    job?.cancel()
}
bqucvtff

bqucvtff2#

即使viewModelScope被取消,流也会继续收集,因为它不配合取消。
要使流可取消,您可以执行以下操作之一:
1.在collect lambda中,调用currentCoroutineContext().ensureActive()来确保收集流的上下文仍然是活动的,但是如果协程作用域已经被取消(对于您的情况是viewModel作用域),这将抛出一个CancellableException,您需要捕获它。
1.可以按如下方式使用cancellable()运算符:
并且,当你想取消流时,你可以调用cancel()
有关取消流程的官方文档,请参见:
https://kotlinlang.org/docs/flow.html#flow-cancellation-checks

uxh89sit

uxh89sit3#

我相信你想要这样的东西

lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        state.collect { 
        }
    }
}

这里有一篇关于重复生命周期的优秀文章:https://medium.com/androiddevelopers/repeatonlifecycle-api-design-story-8670d1a7d333

相关问题