关于此问题有很多类似的问题,但用法一直在发生变化;这是我发现的唯一一个专门讨论 MutableSets、MutableStateFlows 和 collectAsState() 的问题。
问题是,当我向 MutableSet 添加元素时,可组合项不会重新组合。以下代码是我所能得到的最简单的代码,但仍然显示了问题。
视图模型
class MyViewmodel : ViewModel() {
private val _infoSet = MutableStateFlow(mutableSetOf<MyInfo>())
val infoSet = _infoSet.asStateFlow()
fun add() {
val newInfo = MyInfo(num = infoSet.value.size + 1)
_infoSet.value.add(newInfo)
Log.d(TAG, "infoSet is now ${infoSet.value}")
}
}
data class MyInfo(
val name: String = "foo",
val num: Int = -1
)
主要活动
class MainActivity : ComponentActivity() {
private lateinit var myViewmodel: MyViewmodel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
myViewmodel = MyViewmodel()
setContent {
val infoSet by myViewmodel.infoSet.collectAsStateWithLifecycle()
RecompositionTestTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
DrawStuff(
modifier = Modifier.padding(innerPadding),
infoSet = infoSet,
myViewmodel
)
}
}
}
}
}
@Composable
fun DrawStuff(
modifier: Modifier = Modifier,
infoSet: Set<MyInfo>,
viewmodel: MyViewmodel
) {
Log.d(TAG, "DrawStuff() start")
LazyColumn(modifier = modifier.safeDrawingPadding()) {
item { Text("This should display a Set of MyInfo") }
item {
Button(
onClick = {
viewmodel.add()
Toast.makeText(ctx, "infoSet = $infoSet", Toast.LENGTH_SHORT).show()
}
) { Text("add") }
}
// the MyInfo list
infoSet.forEach { info ->
Log.d(TAG, "listing the MyInfos $info")
item {
Text("${info.name}, ${info.num}")
}
}
}
}
日志语句显示单击按钮会调用 MyViewmodel.add()。但日志也清楚地显示 DrawStuff 未被调用。出乎意料的是,Toast 消息正确显示了信息。
我这里做错了什么吗?我需要做什么才能在内容发生变化时DrawStuff()
显示内容infoSet
?(注意:我已经进行了测试,其中 infoSet 已预先加载了数据。它可以正确绘制,但在添加项目时仍然不会改变。)