可变列表更改时视图不会重构



我有一个在视图模型中有一个状态列表的应用程序。我有一个函数,在列表中添加一个数字。当我点击一个按钮时,它会在列表中添加数字。但这些变化并没有反映在另一个视图中。

MainActivity.kt

class MainActivity : ComponentActivity() {
private val viewModel by viewModels<MainViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApplicationTheme {
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
Column {
Button(onClick = {viewModel.increaseCounter()}) {
Text("Increase counter")
}
CountView(viewModel.counter)
}
}
}
}
}
}
@SuppressLint("CoroutineCreationDuringComposition")
@Composable
fun CountView(count: List<Int>) {
var coroutineScope = rememberCoroutineScope()
coroutineScope.launch {
Log.d("inside the coroutine ${count}")
}
}

MainViewModel.kt

class MainViewModel: ViewModel() {
var counter = mutableStateListOf<Int>()
fun increaseCounter() {
Log.d(">>>", "in viewmodel ${counter.size}")
counter.add(1)
}
}

预期的结果:当我点击按钮日志打印,因为它添加了许多mutableStateList。

但是当我将mutableStateListOf更改为mutableStateOf并存储一些整数并更改整数时,视图会重新组合并在点击按钮时打印日志

函数不重组的主要问题是,您没有使用视图本身的值,因此Compose缓存它。如果你添加Text(count.joinToString { it.to() })到你的视图,它将会工作。


但是首先你不应该直接从可组合函数中使用协程。添加@SuppressLint("CoroutineCreationDuringComposition")不是IDE显示给您的错误的正确解决方案:

调用启动应该发生在LaunchedEffect中,而不是组合

所以你的代码应该是这样的:
@Composable
fun CountView(count: List<Int>) {
LaunchedEffect(count) {
println("inside the coroutine $count")
}
}

这在您的情况下也不起作用,因为对于mutableStateListOf,LaunchedEffect通过指针比较键,并且由于这仍然是相同的容器,LaunchedEffect将不会重新启动。要通过引用进行比较,传递一个普通列表更简洁:

CountView(viewModel.counter.toList())

请注意,在LaunchedEffect中,您已经在协程范围内,并且可以运行挂起函数。

rememberCoroutineScope通常在需要从其他副作用(如button click)启动协程时使用。

阅读关于副作用的文档

最新更新