使用Hilt注入SavedStateHandle回传页面结果失效问题
问题原因分析:注入的SavedStateHandle无法获取回传结果
本质是实例不匹配:
- 通过Hilt注入到ViewModel的
SavedStateHandle,是ViewModel自身专属的状态容器,和导航组件的页面栈无关; - 而
navController.currentBackStackEntry?.savedStateHandle是导航组件中当前页面BackStackEntry对应的状态容器,二者是完全独立的实例。
你回传结果时,是把值设置到了**上一个BackStackEntry的SavedStateHandle**里,ViewModel持有的实例根本没被修改,自然收不到结果。
两种解决方式
方式1:让ViewModel绑定BackStackEntry的SavedStateHandle
修改ViewModel的注入逻辑,让它接收和当前页面BackStackEntry绑定的SavedStateHandle:
@HiltViewModel class CreatePostViewModel @Inject constructor( private val savedStateHandle: SavedStateHandle, ) : ViewModel() { init { viewModelScope.launch { savedStateHandle.getStateFlow("result", "").collect { Timber.d("Result -> $it") } } } }
在Compose页面中,创建ViewModel时传入当前BackStackEntry:
fun CreatePostScreen( navController: NavController, coroutineScope: CoroutineScope, snackbarState: SnackbarHostState, ) { val backStackEntry = navController.currentBackStackEntry!! val viewModel: CreatePostViewModel = hiltViewModel(backStackEntry) // 原监听逻辑可移除,ViewModel内的collect会自动接收结果 }
方式2:手动传递结果到ViewModel
如果不想修改ViewModel的注入方式,可以在Compose中监听BackStackEntry的SavedStateHandle,拿到结果后主动传递给ViewModel:
fun CreatePostScreen( navController: NavController, coroutineScope: CoroutineScope, snackbarState: SnackbarHostState, viewModel: CreatePostViewModel = hiltViewModel(), ) { LaunchedEffect(key1 = Unit) { navController.currentBackStackEntry?.savedStateHandle?.getStateFlow("result", "")?.collect { result -> viewModel.onResultReceived(result) } } }
ViewModel中添加处理方法:
fun onResultReceived(result: String) { Timber.d("Result -> $result") // 后续业务逻辑处理 }
内容的提问来源于stack exchange,提问作者Malik Bilal
相关产品推荐
相关产品推荐

