根据我对导航图作用域视图模型的理解,当关联导航图从导航堆栈中弹出时,应该立即调用它们的onCleared
方法。我看到的是,在onCleared
真正被调用之前,还需要几个导航调用。
在MainActivity.kt内部:
val swipeDismissableNavController = rememberSwipeDismissableNavController()
swipeDismissableNavController.addOnDestinationChangedListener(NavController.OnDestinationChangedListener { controller, destination, arguments ->
try {
controller.getBackStackEntry("chat")
} catch(e: IllegalArgumentException) {
Log.d(TAG, "Not on stack")
}
Log.d(TAG, "Route: " + destination.route)
})
SwipeDismissableNavHost(
navController = swipeDismissableNavController,
startDestination = "home"
) {
navigation(
startDestination = "messages",
route = "chat"
) {
composable(
route = "messages"
) {
val backStackEntry = remember { swipeDismissableNavController.getBackStackEntry("chat") }
val chatViewModel: ChatViewModel = viewModel(backStackEntry)
...
}
composable(
route = "image"
) {
val backStackEntry = remember { swipeDismissableNavController.getBackStackEntry("chat") }
val chatViewModel: ChatViewModel = viewModel(backStackEntry)
...
}
}
...
}
内部ChatViewModel.kt
class ChatViewModel(): ViewModel() {
...
init {
Log.d(TAG, "init")
}
override fun onCleared() {
super.onCleared()
Log.d(TAG, "onCleared")
}
}
我观察到的是以下行为:
当我导航到chat
时,视图模型被正确地创建为打印init
。通过在chat
图中导航,视图模型实例被正确重用。然而,当我从chat
图中导航时,我看到Not on stack
正在打印,但是onCleared
没有打印出来。只有在进行了一些额外的导航之后,onCleared
最终才会被打印出来。
有人知道为什么onCleared
会被延迟吗?
打印堆栈看起来类似于:
Not on Stack
Route: home
Route: messages
init
Not on Stack
Route: home
** (THIS IS WHERE I WOULD EXPECT TO SEE onCleared) **
Not on Stack
Route: settings
Not on Stack
Route: home
onCleared
但是,如果我在chat
图中执行更多的导航操作,那么onCleared
的调用是正确的:
Not on Stack
Route: home
Route: messages
init
Route: image
Route: messages
Route: image
Route: messages
Route: image
Route: messages
Not on Stack
Route: home
onCleared
发布于 2022-03-22 18:11:35
我也有过类似的问题。
在默认情况下,组合将viewModels链接到视图层次结构中最近的片段或活动,该层次结构控制那些viewModels的生存期,就像它是非组合世界一样。
我已经通过使用自定义ViewModelOwner +DisposableEffect解决了这个问题:
if (selectedParkingAreaId != null) {
val viewModelStore = remember(selectedParkingAreaId) { ViewModelStore() }
DisposableEffect(selectedParkingAreaId) {
onDispose { viewModelStore.clear() }
}
val viewModel: WheelScreenViewModel =
viewModel(viewModelStoreOwner = { viewModelStore })
...
}
然后,当selectedParkingAreaId
为null时,if
部分将被排除在触发DisposableEffect.onDispose{...}
(清除调用WheelScreenViewModel.onCleared的ViewModelStore
)的组合中。
不是超级优雅,而是功能性。
https://stackoverflow.com/questions/70640127
复制相似问题