You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的依赖注入:

  1. 添加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")
  1. 在Application类添加@HiltAndroidApp注解:
@HiltAndroidApp
class SpaceTrackerApplication : Application()
  1. 修改ViewModel,添加@HiltViewModel和构造函数的@Inject注解:
@HiltViewModel
class RocketsViewModel @Inject constructor(private val rocketRepository : RocketRepository) : ViewModel(){
    // 原有代码不变
}
  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 04:21:03