Android Studio Kotlin无法创建ViewModel问题求助
ViewModel初始化崩溃问题解决
错误日志
FATAL EXCEPTION: main Process: be.example.spacetracker, PID: 10985 java.lang.RuntimeException: Cannot create an instance of class be.example.spacetracker.viewmodel.RocketsViewModel 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.viewmodel.compose.ViewModelKt.get(ViewModel.kt:215) at androidx.lifecycle.viewmodel.compose.ViewModelKt.viewModel(ViewModel.kt:156) at be.thijsgeeraert.spacetracker.ui.screen.RocketScreenKt.RocketScreen(RocketScreen.kt:103) ...(省略后续栈信息) Caused by: java.lang.NoSuchMethodException: be.example.spacetracker.viewmodel.RocketsViewModel.<init> [] 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) ... 219 more
相关代码
ViewModel代码
class RocketsViewModel(private val rocketRepository : RocketRepository) : ViewModel(){ var rocketUiState: RocketUiState by mutableStateOf(RocketUiState.Loading) private set init { Log.d("debug","HulpInInit") getRockets() } fun getRockets() { viewModelScope.launch { rocketUiState = RocketUiState.Loading rocketUiState = try { RocketUiState.Success(rocketRepository.getAllRockets()) } catch (e: IOException){ RocketUiState.Error } catch (e: HttpException){ RocketUiState.Error } } } }
调用ViewModel的Composable代码
@Composable fun RocketScreen( modifier: Modifier = Modifier) { Log.d("debug","hulpbeforecreationvm") val viewModel : RocketsViewModel = viewModel() Log.d("debug","hulpbeforecreationui") val rocketUiState: RocketUiState = viewModel.rocketUiState when (rocketUiState) { is RocketUiState.Loading -> LoadingScreen(modifier = modifier.fillMaxSize()) is RocketUiState.Success -> ResultScreen(response = rocketUiState.response, modifier = modifier.fillMaxSize()) is RocketUiState.Error -> ErrorScreen(modifier = modifier.fillMaxSize()) } }
依赖配置
dependencies { implementation("androidx.compose.ui:ui-geometry-android:1.5.4") implementation("androidx.core:core-ktx:1.9.0") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2") implementation("androidx.activity:activity-compose:1.7.1") implementation(platform("androidx.compose:compose-bom:2023.03.00")) implementation("androidx.compose.ui:ui") implementation("androidx.compose.ui:ui-graphics") implementation("androidx.compose.ui:ui-tooling-preview") implementation("androidx.compose.material3:material3") // Retrofit implementation("com.squareup.retrofit2:retrofit:2.9.0") // Retrofit with Scalar Converter implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2") implementation("com.squareup.retrofit2:converter-scalars:2.9.0") implementation("androidx.room:room-ktx:2.6.1") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1") testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.1.5") androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") androidTestImplementation(platform("androidx.compose:compose-bom:2023.03.00")) androidTestImplementation("androidx.compose.ui:ui-test-junit4") debugImplementation("androidx.compose.ui:ui-tooling") debugImplementation("androidx.compose.ui:ui-test-manifest") }
问题原因
RocketsViewModel只有带RocketRepository参数的构造函数,而Compose默认的viewModel()方法仅能创建无参构造的ViewModel实例,系统找不到对应的无参构造方法,因此抛出NoSuchMethodException导致崩溃。
解决方法
方法一:手动实现ViewModelFactory
创建自定义Factory类,负责创建带参数的ViewModel:
class RocketsViewModelFactory(private val rocketRepository: RocketRepository) : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>): T { if (modelClass.isAssignableFrom(RocketsViewModel::class.java)) { @Suppress("UNCHECKED_CAST") return RocketsViewModel(rocketRepository) as T } throw IllegalArgumentException("未知的ViewModel类") } }
在Composable中传入Factory实例获取ViewModel:
@Composable fun RocketScreen( modifier: Modifier = Modifier, // 传入已初始化的RocketRepository实例,可通过单例、参数传递等方式获取 viewModel: RocketsViewModel = viewModel( factory = RocketsViewModelFactory(yourRocketRepositoryInstance) ) ) { Log.d("debug","hulpbeforecreationvm") val rocketUiState: RocketUiState = viewModel.rocketUiState when (rocketUiState) { is RocketUiState.Loading -> LoadingScreen(modifier = modifier.fillMaxSize()) is RocketUiState.Success -> ResultScreen(response = rocketUiState.response, modifier = modifier.fillMaxSize()) is RocketUiState.Error -> ErrorScreen(modifier = modifier.fillMaxSize()) } }
方法二:使用Hilt依赖注入(推荐)
通过Hilt可更优雅地处理ViewModel的依赖注入:
- 添加Hilt相关依赖到Module级
build.gradle:
// Hilt核心依赖 implementation("com.google.dagger:hilt-android:2.48") kapt("com.google.dagger:hilt-android-compiler:2.48") // Hilt Compose支持 implementation("androidx.hilt:hilt-navigation-compose:1.1.0")
- 在Application类添加
@HiltAndroidApp注解:
@HiltAndroidApp class SpaceTrackerApplication : Application()
- 修改ViewModel,添加
@HiltViewModel和构造函数的@Inject注解:
@HiltViewModel class RocketsViewModel @Inject constructor(private val rocketRepository : RocketRepository) : ViewModel(){ // 原有代码不变 }
- 在Composable中使用
hiltViewModel()获取ViewModel:
@Composable fun RocketScreen(modifier: Modifier = Modifier) { Log.d("debug","hulpbeforecreationvm") val viewModel : RocketsViewModel = hiltViewModel() Log.d("debug","hulpbeforecreationui") val rocketUiState: RocketUiState = viewModel.rocketUiState when (rocketUiState) { is RocketUiState.Loading -> LoadingScreen(modifier = modifier.fillMaxSize()) is RocketUiState.Success -> ResultScreen(response = rocketUiState.response, modifier = modifier.fillMaxSize()) is RocketUiState.Error -> ErrorScreen(modifier = modifier.fillMaxSize()) } }
注意事项
- 手动Factory方式需确保
RocketRepository实例已正确初始化(如单例、依赖注入等)。 - 使用Hilt时需完成基础配置(如Application类注解、插件引入)。
内容的提问来源于stack exchange,提问作者Eeplo
相关产品推荐
相关产品推荐

