StateFlow 在活动暂停和恢复时会不断发出信号。

10

我有一个状态流,在HTTP请求返回响应后会发出一个值,该值将显示为Activity中的列表,我正在使用Kotlin coroutines StateFlow来实现ViewModel和Activity之间的通信。

我正在像这样使用androidx生命周期repeatOnLifecycle函数:

lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        viewModel.successFlow.collect { binding.recyclerView.adapter = ExampleAdapter(it) }
    }
}

起初这个功能很好用,但后来发现每次用户切换到其他屏幕再返回到之前的屏幕时,状态流会重新发送值,这种情况下会丢失列表状态。例如,如果用户滚动到列表项10,然后转到另一个屏幕并返回,则列表将滚动到位置0,因为再次调用了setAdapter方法,而使用LiveData则不会出现这种情况。

现在我需要处理StateFlow状态和配置状态,我尝试使用distinctUntilChanged方法,但文档中说将'distinctUntilChanged'应用于StateFlow没有效果

问题是如何使用StateFlow实现相同的LiveData行为。

1个回答

5
你遇到了一个问题,这个问题在Medium文章中最近被描述过。每个流集合都会重新开始,并且即使它没有改变,它也会一遍又一遍地接收到值。另一方面,LiveData知道每个观察者已经看到的数据的版本,并且只会发送再次发布的数据。
解决你的问题的简单方法是将数据存储在某个地方并检查它是否已更改。你还可以使用flowWithLifecycle()收集流,并对其进行distinctUntilChanged()操作(请注意,在此之后使用缓冲运算符可能会丢失值发射,如上面链接的文章所述)。
它看起来像这样:
viewModel.successFlow.flowWithLifecycle(lifecycle).distinctUntilChanged().onEach {
    binding.recyclerView.adapter = ExampleAdapter(it)
}.launchIn(lifecycleScope)


然而,我认为您不应该在每次数据更改时替换适配器!您应该执行以下操作:
(binding.recyclerView.adapter as ListAdapter<*,*>).submitList(it)

当然,为了使其正常工作,您应该使用ListAdapter。

有了这个,当新数据到达时,无论是相同的还是不同的数据,都不会受到任何干扰。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接