如何只监听MutableStateFlow类型列表中的特定元素?如果我们监听整个列表,那么所有正在监听列表的视图如果被改变,将重建它们自己,这是我不希望的。
class ArticleViewModel: ViewModel() {
val articles = MutableStateFlow<List<Article>>( /* articles list */)
}
@Composable
fun ArticlePreview (index: Int) {
val model: ArticleViewModel: viewModel();
// Problem: Since it is listening to entire list. If the list changes, the entire ArticlePreview widgets will rebuild but I only want to change a particular item if some property of the current item changes in the list.
val previews by model.articles.collectAsState();
val currentPreview = previews[index];
Text(text = currentPreview.body);
}
4条答案
按热度按时间6yjfywim1#
Compose通常足够聪明,可以自己解决这个问题:它“知道”旧列表,“知道”新列表,因此它“知道”差异。然后,它应该只重组差异。
但是,这需要使用equals函数。最简单的方法是确保您的
Article
是data class
。如果改变了,观点会重新建立自己,这是我不想要的。
虽然不希望过多地重建ui,但您必须习惯于不时地编写重建ui
g2ieeal72#
您可以在compose函数中使用
derivedStateOf
,如下所示:derivedStateOf
函数仅在特定数据发生更改时触发更新,从而有效地管理用户界面的重组。此优化可以通过减少整个屏幕的不必要重绘次数来显著提高应用性能。628mspwn3#
如果你不想监听整个列表,那么你应该有另一个
mutableStateFlow
,它只包含一个Article
。你应该有一个函数将索引传递给viewModel
,并触发新的mutableStateFlow
。所以你的整个widget不会更新。此
selectedArticle
函数将触发article
状态流,您可以从组合工具中收集该状态流。如果你的列表改变了,你的小部件组合也不会更新。but5z9lq4#
要更改流量数据,可以使用
map
。它返回一个流,为了在composable中具有非可选值,您可以使用
stateIn
从它构建状态流为了使代码更简洁,我使用了以下扩展-它将相同的
transform
应用于初始值和Map值:然后你可以很容易地在composable中使用它:
在这种情况下,
StateFlow
生命周期将绑定到Composable。请注意,mapState
应该在remember
内部调用,以防止重新组合时的额外工作。通常你可以在视图模型中使用相同的技术-但是如果你的
map
依赖于index
参数,那么在视图级别上更容易。