创建ViewModel时出现Cannot create an instance of class错误求助
问题:Cannot create an instance of class ViewModel错误
创建ViewModel时触发Cannot create an instance of class错误,应用在ViewModel初始化阶段崩溃,多次重构相关类仍未解决。
相关代码
Activity类
@AndroidEntryPoint class FamiliarActivity : AppCompatActivity() { private val noticeScreenViewModel : NoticeScreenViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { FamiliarTheme { val navController = rememberNavController() val currentBackStack by navController.currentBackStackEntryAsState() val currentDestination = currentBackStack?.destination val currentScreen = familiarScreens.find { it.route == currentDestination?.route } ?: Settings FamiliarNavHost( noticesViewModel = noticeScreenViewModel, navController = navController, modifier = Modifier.padding() ) } } } }
NoticeScreenViewModel类
@HiltViewModel class NoticeScreenViewModel @Inject internal constructor( private val noticeRepository: NoticeRepository ) : ViewModel(){ val notices: List<Notice> = noticeRepository.getNotices() }
NoticeRepository类
class NoticeRepository @Inject constructor( private val noticeDao: NoticeDao ) { fun createNotice(notice: Notice) { noticeDao.insert(notice) } fun removeNotice(notice: Notice) { noticeDao.delete(notice) } fun getNotices() = noticeDao.getNotices() companion object { // For Singleton instantiation @Volatile private var instance: NoticeRepository? = null fun getInstance(noticeDao: NoticeDao) = instance ?: synchronized(this) { instance ?: NoticeRepository(noticeDao).also { instance = it } } } }
NoticeDao接口
@Dao interface NoticeDao { @Query("SELECT * FROM notice") fun getNotices(): List<Notice> @Insert fun insertAll(vararg notices: Notice) @Insert fun insert(notice: Notice) @Delete fun delete(notice: Notice) }
崩溃堆栈信息
FATAL EXCEPTION: main Process: com.dmlpcb.familiar, PID: 27627 java.lang.RuntimeException: Cannot create an instance of class com.dmlpcb.familiar.ui.NoticeScreenViewModel at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.kt:204) at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:324) at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:306) at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:280) at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.kt:128) at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:187) at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:153) at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:53) at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:35) at com.dmlpcb.familiar.FamiliarActivity$noticeScreenViewModel$2.invoke(FamiliarActivity.kt:23) at com.dmlpcb.familiar.FamiliarActivity$noticeScreenViewModel$2.invoke(FamiliarActivity.kt:22) at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74) at com.dmlpcb.familiar.FamiliarActivity.getNoticeScreenViewModel(FamiliarActivity.kt:22) at com.dmlpcb.familiar.FamiliarActivity.access$getNoticeScreenViewModel(FamiliarActivity.kt:19) at com.dmlpcb.familiar.FamiliarActivity$onCreate$1$1.invoke(FamiliarActivity.kt:36) at com.dmlpcb.familiar.FamiliarActivity$onCreate$1$1.invoke(FamiliarActivity.kt:28) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228) at androidx.compose.material3.TextKt.ProvideTextStyle(Text.kt:360) at androidx.compose.material3.MaterialThemeKt$MaterialTheme$1.invoke(MaterialTheme.kt:81) at androidx.compose.material3.MaterialThemeKt$MaterialTheme$1.invoke(MaterialTheme.kt:80) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228) at androidx.compose.material3.MaterialThemeKt.MaterialTheme(MaterialTheme.kt:73) at com.dmlpcb.familiar.compose.ThemesKt.FamiliarTheme(Themes.kt:22) at com.dmlpcb.familiar.FamiliarActivity$onCreate$1.invoke(FamiliarActivity.kt:28) at com.dmlpcb.familiar.FamiliarActivity$onCreate$1.invoke(FamiliarActivity.kt:27) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) at androidx.compose.ui.platform.ComposeView.Content(ComposeView.android.kt:428) at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:252) at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:251) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228) at androidx.compose.ui.platform.CompositionLocalsKt.ProvideCommonCompositionLocals(CompositionLocals.kt:195) at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:119) at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:118) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228) at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt.ProvideAndroidCompositionLocals(AndroidCompositionLocals.android.kt:110) at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$2.invoke(Wrapper.android.kt:158) at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$2.invoke(Wrapper.android.kt:157) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228) at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:157) at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:142) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) at androidx.compose.runtime.ActualJvm_jvmKt.invokeComposable(ActualJvm.jvm.kt:78) at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3340) at androidx.compose.runtime.ComposerImpl.composeContent$runtime_release(Composer.kt:3273) at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:588) at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:1013) at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:520) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:142) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:133) at androidx.compose.ui.platform.AndroidComposeView.setOnViewTreeOwnersAvailable(AndroidComposeView.android.kt:1191) at androidx.compose.ui.platform.WrappedComposition.setContent(Wrapper.android.kt:133) at androidx.compose.ui.platform.WrappedComposition.onStateChanged(Wrapper.android.kt:183) at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.kt:314) at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.kt:192) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:140) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:133) at androidx.compose.ui.platform.AndroidComposeView.onAttachedToWindow(AndroidComposeView.android.kt:1266) at android.view.View.dispatchAttachedToWindow(View.java:21980) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3490) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3014) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2465) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9305) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1339) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1348) at android.view.Choreographer.doCallbacks(Choreographer.java:952) at android.view.Choreographer.doFrame(Choreographer.java:882) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1322) at android.os.Handler.handleCallback(Handler.java:958) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:205) at android.os.Looper.loop(Looper.java:294) at android.app.ActivityThread.main(ActivityThread.java:8177) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971) Caused by: java.lang.NoSuchMethodException: com.dmlpcb.familiar.ui.NoticeScreenViewModel. [] at java.lang.Class.getConstructor0(Class.java:3325) at java.lang.Class.getDeclaredConstructor(Class.java:3063) at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.kt:202) ... 92 more
解决方案
从崩溃栈的Caused by: java.lang.NoSuchMethodException: ... []可知,系统尝试寻找ViewModel的无参构造函数,但当前ViewModel使用Hilt依赖注入,问题核心是Hilt未正确接管ViewModel的创建流程,按以下步骤排查修复:
确认Hilt依赖配置完整
- 项目级
build.gradle需添加Hilt插件:plugins { id 'com.android.application' version 'xxx' apply false id 'org.jetbrains.kotlin.android' version 'xxx' apply false id 'com.google.dagger.hilt.android' version 'xxx' apply false } - 模块级
build.gradle需启用Hilt插件并添加依赖:plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' id 'com.google.dagger.hilt.android' } dependencies { implementation "com.google.dagger:hilt-android:xxx" kapt "com.google.dagger:hilt-compiler:xxx" implementation "androidx.hilt:hilt-lifecycle-viewmodel:xxx" kapt "androidx.hilt:hilt-compiler:xxx" }
- 项目级
检查Application类的Hilt注解
Hilt需要通过标记@HiltAndroidApp的Application类初始化依赖容器,确保存在该类:@HiltAndroidApp class MyApplication : Application() { // 空实现或自定义逻辑 }同时在
AndroidManifest.xml中指定该Application:<application android:name=".MyApplication" <!-- 其他配置项 --> > </application>修正ViewModel的初始化方式
对于Hilt注入的ViewModel,需使用Hilt提供的扩展函数获取:- 若在Compose NavHost中使用,直接在目标页面调用
hiltViewModel():@Composable fun FamiliarNavHost(navController: NavHostController, modifier: Modifier = Modifier) { NavHost(navController = navController, startDestination = "xxx") { composable("xxx") { val viewModel: NoticeScreenViewModel = hiltViewModel() // 使用viewModel构建UI } } } - 若需在Activity中获取,确保导入Hilt的
viewModels()扩展:import androidx.hilt.lifecycle.viewModels // 初始化代码保持不变,但需确保导入正确 private val noticeScreenViewModel : NoticeScreenViewModel by viewModels()
- 若在Compose NavHost中使用,直接在目标页面调用
调整Repository与Dao的注入逻辑
- 移除NoticeRepository中的单例companion object,Hilt会自动管理实例生命周期,手动单例会与Hilt注入逻辑冲突,仅保留
@Inject constructor即可。 - 确保Room数据库类被Hilt正确提供:
@Database(entities = [Notice::class], version = 1) abstract class AppDatabase : RoomDatabase() { abstract fun noticeDao(): NoticeDao } @Module @InstallIn(SingletonComponent::class) object DatabaseModule { @Provides @Singleton fun provideAppDatabase(@ApplicationContext context: Context): AppDatabase { return Room.databaseBuilder( context, AppDatabase::class.java, "app_database" ).build() } @Provides fun provideNoticeDao(appDatabase: AppDatabase): NoticeDao { return appDatabase.noticeDao() } }
- 移除NoticeRepository中的单例companion object,Hilt会自动管理实例生命周期,手动单例会与Hilt注入逻辑冲突,仅保留
清理缓存并重新构建项目
编译缓存可能导致Hilt生成的代码异常,执行Build -> Clean Project和Build -> Rebuild Project,或删除项目根目录下的.gradle、build文件夹后重新编译。
内容的提问来源于stack exchange,提问作者Edmund Osborne
相关产品推荐
相关产品推荐

