我需要你的帮助
我正在从iOS移植一个大型应用程序(iPad))到Android (仅限平板电脑)),使用Jetpack Compose.
这是上下文。我有一个Pins(地图上的对象)列表。pin是一个非常复杂的元素,有许多参数(状态、照片、历史以及大约20多个参数)。当我在列表中选择一个引脚时,我希望显示一个包含该引脚所有细节的对话框。这是我的代码。
fun PinList(viewModel: PinListViewModel) {
…
LazyColumn(..) {
items(viewModel.pins, key = {it.identifier}) { pin ->
PinCell(pin, …)
}
}
…
}
private fun PinCell(pin: Pin, …) {
var showDetails by remember { mutableStateOf(false)) }
…
Row(modifier = Modifier.clickable { showDetails = true }, …) {
…
}
…
if (showDetails) {
PinDetailsDialog(pin, onDismissRequest = { showDetails = false }
}
}
细节视图是如此复杂,我需要一个viewModel来管理它(引脚参数可以编辑)
fun PinDetailsDialog(pin: Pin, onDismissRequest: () -> Unit) {
val viewModel: PinDetailsViewModel = viewModel()
viewModel.pin = pin // Needed !!
Dialog(onDismissRequest = onDismissRequest, …) {
…
}
DisposableEffect(Unit) {
Log.d(TAG, "PinDetailsDialog onAppear")
onDispose {
Log.d(TAG, "PinDetailsDialog onDispose")
}
}
}
最后,viewModel
class PinDetailsViewModel: ViewModel() {
…
init {
Log.d(TAG, "PinDetailsViewModel init")
}
override fun onCleared() {
Log.d(TAG, "PinDetailsViewModel onCleared")
}
…
}
OK。现在问题来了:-)
我运行应用程序,在列表中选择一个引脚并获得日志
PinDetailsViewModel init
PinDetailsDialog onAppear
关闭对话框
PinDetailsDialog onDispose
可以看到,对话框被处理了,但viewModel从未被清除。我知道为什么。PinDetailsDialog保存在PinCell的合成树缓存中,永远不会被释放。这是一个问题,因为这个viewModel是巨大的,永远不会在整个应用运行过程中被释放。我以后还会遇到其他类似的病例。
我希望PinDetailsViewModel在我关闭对话框时被释放。
有人知道解决办法吗?
谢谢你的帮助!
您可以尝试在"一次性效果"中手动清除ViewModel
,即
val context = LocalContext.current as Activity
DisposableEffect(key1 = "Dialog Reference/Key", effect = {
onDispose {
context.viewModelStore.clear()
}
})