Jetpack Compose中NavHost启动时LoginViewModel实例创建失败
问题场景
直接将RegistrationFrame2()作为独立Composable组件运行时程序正常,但将其作为NavHost的起始目标时,抛出以下错误:
Process: com.example.application_digital, PID: 5298 java.lang.RuntimeException: Cannot create an instance of class com.example.application_digital.features.registration.presentation. login.view_models.LoginViewModel Caused by: java.lang.InstantiationException: java.lang.Class<com.example.application_digital.features. registration.presentation.login.view_models.LoginViewModel> has no zero argument constructor
报错原因
你的LoginViewModel使用@HiltViewModel注解,依赖Hilt完成依赖注入,构造函数包含多个参数而非无参构造。但在Composable中调用viewModel<LoginViewModel>()时,默认会使用ViewModelProvider的默认Factory,它要求ViewModel必须有无参构造函数。
直接运行RegistrationFrame2时能正常工作,是因为父组件(如测试用Activity)已配置Hilt,ViewModel实例化走了Hilt的注入逻辑;但在NavHost中,默认的ViewModel获取方式未关联Hilt的注入机制,导致无法实例化带参数的ViewModel。
解决步骤
1. 替换ViewModel获取方式
在RegistrationFrame2中,将所有使用viewModel()获取ViewModel的代码替换为Hilt提供的hiltViewModel()方法:
修改前:
val tabViewModel = viewModel<TabRowViewModel>() val loginViewModel = viewModel<LoginViewModel>() val signupViewModel = viewModel<SignupViewModel>()
修改后:
val tabViewModel = hiltViewModel<TabRowViewModel>() val loginViewModel = hiltViewModel<LoginViewModel>() val signupViewModel = hiltViewModel<SignupViewModel>()
2. 确保父组件已配置Hilt
- 你的Application类必须添加
@HiltAndroidApp注解:
@HiltAndroidApp class MyApplication : Application() { // ... }
- 承载NavHost的Activity必须添加
@AndroidEntryPoint注解:
@AndroidEntryPoint class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { val navController = rememberNavController() RootNavigator(navController) } } }
3. 验证其他ViewModel的注解
确保TabRowViewModel和SignupViewModel也添加了@HiltViewModel注解,并且构造函数使用@Inject注解,和LoginViewModel的写法保持一致。
修改后的RegistrationFrame2关键代码片段
@Composable fun RegistrationFrame2() { val context = LocalContext.current val focusRequester = remember { FocusRequester() } // 使用hiltViewModel替代viewModel val tabViewModel = hiltViewModel<TabRowViewModel>() val loginViewModel = hiltViewModel<LoginViewModel>() val signupViewModel = hiltViewModel<SignupViewModel>() val initialText = tabViewModel.getRegistrationInitialText(context) val focusManager = LocalFocusManager.current // 后续代码保持不变... }
内容的提问来源于stack exchange,提问作者zero.one
相关产品推荐
相关产品推荐

