ViewModel的SavedStateHandle与currentBackStackEntry是否相同?Activity如何向Fragment的ViewModel传值?
问题解答
1. ViewModel的SavedStateHandle与NavBackStackEntry的savedStateHandle是否为同一对象?
不是同一个对象。两者的生命周期与所属范围完全不同:
- ViewModel默认接收的
SavedStateHandle与Fragment/Activity的ViewModelStore绑定,生命周期跟随对应的组件(比如Fragment的创建与销毁)。 NavBackStackEntry的savedStateHandle与导航栈条目绑定,生命周期跟随导航栈的入栈、出栈操作,当该条目从导航栈移除时,对应的handle也会被销毁。
你在Fragment中直接获取currentBackStackEntry.savedStateHandle能拿到数据,是因为操作的是导航栈条目的handle;但ViewModel里的是另一个独立实例,自然接收不到设置的值。
2. 是否可以直接将数据传递到ViewModel的SavedStateHandle中?
可以,但需要确保ViewModel使用的是导航栈条目的SavedStateHandle,而非默认的组件绑定的handle。具体操作如下:
步骤1:修改Fragment中ViewModel的创建方式
不要使用默认的by viewModels(),而是将ViewModel与导航栈条目绑定,这样ViewModel会使用导航栈条目的SavedStateHandle:
// 在Fragment中使用扩展函数(需依赖Navigation KTX) val viewModel by navGraphViewModels<MyViewModel>(R.id.your_nav_graph_id) // 或者手动创建ViewModel val navBackStackEntry = findNavController().currentBackStackEntry!! val viewModel = ViewModelProvider( navBackStackEntry, SavedStateViewModelFactory(requireActivity().application, this) )[MyViewModel::class.java]
步骤2:保留Activity中的代码逻辑
你在Activity中通过navController.currentBackStackEntry.savedStateHandle.set()设置数据的写法是正确的,只要ViewModel关联了对应的导航栈条目,就能通过自身的SavedStateHandle接收到数据。
验证ViewModel逻辑
你的ViewModel代码无需修改,只要关联了正确的SavedStateHandle,getStateFlow就能正常触发回调:
MyViewModel(state: SavedStateHandle) : ViewModel() { init { state .getStateFlow("foo", "") .onEach { /* 此时能正常接收到"bar"值 */ } .launchIn(viewModelScope) } }
原代码不生效的原因
你原来的ViewModel使用的是Fragment自身的SavedStateHandle,和Activity中操作的导航栈条目handle是两个独立实例,数据无法互通。只有让ViewModel与导航栈条目绑定,才能共享同一个SavedStateHandle实例,实现跨组件的数据传递。
内容的提问来源于stack exchange,提问作者user3119685
相关产品推荐
相关产品推荐

