Koin中Compose的getStateViewModel已弃用,求替代方案及Hilt实现
一、问题背景
在View Fragment中通过Koin的stateViewModel扩展注入HeroesDetailsViewModel,利用导航参数初始化SavedStateHandle的实现可行,但Compose中使用getStateViewModel时收到弃用提示:getStateViewModel will be merged to sharedViewModel - no need anymore of state parameter,需找到Compose环境下的替代方案,同时提供Koin和Dagger-Hilt两种实现方式。
二、Koin实现(Compose环境)
1. ViewModel模块声明
保持原ViewModel构造和模块声明不变,依旧通过params获取SavedStateHandle:
val viewModelModule = module { viewModel { params -> HeroesDetailsViewModel(params.get(), get()) } }
2. Compose中注入ViewModel
弃用getStateViewModel后,改用sharedViewModel,通过navArgs传递参数初始化SavedStateHandle:
@Composable fun HeroesDetailsScreen(navController: NavController) { // 获取导航参数 val navArgs = HeroesDetailsScreenArgs.fromNavArgs(navController.currentBackStackEntry!!.arguments) // 使用sharedViewModel注入,传入参数初始化SavedStateHandle val viewModel = sharedViewModel<HeroesDetailsViewModel>( state = { navArgs.toBundle() } ) // 后续UI逻辑... }
若使用Jetpack Compose Navigation的自动参数同步特性,也可直接让导航组件将参数存入SavedStateHandle,无需手动传递bundle:
@Composable fun HeroesDetailsScreen( viewModel: HeroesDetailsViewModel = sharedViewModel() ) { // ViewModel内部直接从SavedStateHandle取参数 val navArgs = viewModel.getArgsModel() // 后续UI逻辑... }
三、Dagger-Hilt实现(Compose + ViewModel)
1. 配置依赖
确保项目引入Hilt核心依赖及hilt-navigation-compose扩展。
2. ViewModel添加Hilt注解
给HeroesDetailsViewModel添加@HiltViewModel注解,构造函数通过Hilt注入依赖:
@HiltViewModel class HeroesDetailsViewModel @Inject constructor( private val savedStateHandle: SavedStateHandle, private val heroesDetailsRepository: HeroesDetailsRepository ) : ViewModel() { private fun getArgsModel() = HeroesDetailsFragmentArgs.fromSavedStateHandle(savedStateHandle) init { val navArgs = getArgsModel() getAdditionalHeroDetails(navArgs.heroModel.id) observeUiEvents() } }
3. Compose中注入ViewModel
使用Hilt提供的hiltViewModel()扩展,导航参数会自动被导航组件存入SavedStateHandle:
@Composable fun HeroesDetailsScreen( viewModel: HeroesDetailsViewModel = hiltViewModel() ) { val navArgs = viewModel.getArgsModel() // 后续UI逻辑... }
若需手动添加额外参数到SavedStateHandle,可通过创建回调实现:
@Composable fun HeroesDetailsScreen(navController: NavController) { val customArgs = Bundle().apply { putString("custom_key", "custom_value") } val viewModel = hiltViewModel<HeroesDetailsViewModel>( creationCallback = { factory, handle -> handle.setAll(customArgs) factory.create(handle) } ) // 后续UI逻辑... }
四、关键说明
- Koin的
sharedViewModel完全替代getStateViewModel,用法逻辑一致,仅方法名变更,仍支持通过state参数传递bundle初始化SavedStateHandle。 - Dagger-Hilt中
hiltViewModel()会自动关联当前导航栈的SavedStateHandle,导航参数无需手动处理,这是Hilt与Jetpack Navigation的整合特性。
内容的提问来源于stack exchange,提问作者Alon Shlider

