首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Android ViewModel onCleared()调用太晚了

Android ViewModel onCleared()调用太晚了
EN

Stack Overflow用户
提问于 2022-01-09 09:54:18
回答 1查看 599关注 0票数 3

根据我对导航图作用域视图模型的理解,当关联导航图从导航堆栈中弹出时,应该立即调用它们的onCleared方法。我看到的是,在onCleared真正被调用之前,还需要几个导航调用。

在MainActivity.kt内部:

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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会被延迟吗?

打印堆栈看起来类似于:

代码语言:javascript
运行
复制
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的调用是正确的:

代码语言:javascript
运行
复制
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
EN

回答 1

Stack Overflow用户

发布于 2022-03-22 18:11:35

我也有过类似的问题。

在默认情况下,组合将viewModels链接到视图层次结构中最近的片段或活动,该层次结构控制那些viewModels的生存期,就像它是非组合世界一样。

我已经通过使用自定义ViewModelOwner +DisposableEffect解决了这个问题:

代码语言:javascript
运行
复制
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 )的组合中。

不是超级优雅,而是功能性。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70640127

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档