如何在Jetpack Compose中通过Hilt在运行时向ViewModel构造函数传参
解决Jetpack Compose+Hilt中ViewModel接收运行时Stop参数的问题
要实现将Stop对象传入ViewModel构造函数并在初始化时自动加载数据,需要借助Hilt的Assisted Injection来支持运行时参数传递。以下是具体实现步骤:
1. 添加Assisted Injection依赖
在Module级别的build.gradle文件中添加以下依赖:
implementation "androidx.hilt:hilt-assisted:1.1.0" kapt "androidx.hilt:hilt-compiler:1.1.0"
2. 修改ViewModel实现Assisted Injection
调整ViewModel的构造函数,用@Assisted标记运行时传入的Stop参数,同时创建对应的Assisted Factory来生成ViewModel实例。另外将_stop改为非空StateFlow,并在init块中自动触发数据加载:
@HiltViewModel class StopTimesMapViewModel @Inject constructor( private val getStopTimesUseCase: GetStopTimesUseCase, @Assisted private val stop: Stop ): ViewModel() { private val _stop = MutableStateFlow(stop) private val _estimations = MutableStateFlow<Resource<List<StopEstimation>>>(Resource.loading()) val uiState: StateFlow<StopTimesMapUIState> = combine(_stop, _estimations) { stop, estimations -> StopTimesMapUIState( name = "${stop.id} - ${stop.name}", estimations = estimations.data ?: emptyList(), status = estimations.status ) }.stateIn( scope = viewModelScope, started = WhileUiSubscribed, initialValue = StopTimesMapUIState( name = "${stop.id} - ${stop.name}" ) ) init { loadStopEstimations() } private fun loadStopEstimations() { viewModelScope.launch { getStopTimesUseCase(stop.id) .collect { estimations -> _estimations.value = estimations } } } @AssistedFactory interface Factory : AssistedViewModelFactory<StopTimesMapViewModel> { override fun create(assistedParams: SavedStateHandle, stop: Stop): StopTimesMapViewModel } companion object { fun provideFactory( factory: Factory, stop: Stop, savedStateHandle: SavedStateHandle ): ViewModelProvider.Factory = object : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun <T : ViewModel> create(modelClass: Class<T>): T { return factory.create(savedStateHandle, stop) as T } } } }
3. 在Composable中传递Stop参数创建ViewModel
修改StopTimesMapScreen,使用自定义的Factory将stop参数传入ViewModel:
@Composable fun StopTimesMapScreen( modifier: Modifier = Modifier, stop: Stop, onDismissListener: (() -> Unit), viewModel: StopTimesMapViewModel = viewModel( factory = StopTimesMapViewModel.provideFactory( factory = hiltViewModel(), stop = stop, savedStateHandle = rememberSavedStateHandle() ) ) ) { val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) val uiState by viewModel.uiState.collectAsStateWithLifecycle() ModalBottomSheet( modifier = modifier, onDismissRequest = onDismissListener, sheetState = sheetState ) { StopEstimations(status = uiState.status, estimations = uiState.estimations) } }
实现效果
Stop参数变为非空类型,无需处理空值逻辑- ViewModel初始化时自动调用UseCase加载数据,无需在Composable中手动调用
loadStop - 完全遵循Hilt依赖注入规范,同时支持运行时参数传递
内容的提问来源于stack exchange,提问作者Javier Cancio
相关产品推荐
相关产品推荐

