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

Android Hilt注入AuthApi到LoginViewModel时实例创建失败求助

问题:Hilt注入AuthApi到@HiltViewModel时无法实例化ViewModel

为带有@HiltViewModel注解的LoginViewModel构造函数注入AuthApi后,抛出错误:Cannot create an instance of class newjeans.bunnies.auth.viewmodel.LoginViewModel;移除构造函数中的private val authApi: AuthApi参数后,LoginViewModel可正常实例化。

已完成的配置与尝试:

  • 已通过NetworkModule提供AuthApi的单例实例
  • AuthActivity已添加@AndroidEntryPoint注解
  • 尝试过更换Hilt版本、使用hiltViewModel()方法,问题仍未解决

相关代码

LoginViewModel.kt

@HiltViewModel
class LoginViewModel
@Inject constructor(private val authApi: AuthApi) : ViewModel() {

    private val _hidePassword = MutableLiveData(false)
    val hidePassword: LiveData<Boolean>
        get() = _hidePassword

    private val _autoLogin = MutableLiveData(false)
    val autoLogin: LiveData<Boolean>
        get() = _autoLogin

    private val _loginError = MutableLiveData(false)
    val loginError: LiveData<Boolean>
        get() = _loginError

    fun login(userId: String, password: String) {
        viewModelScope.launch {
            kotlin.runCatching {
                authApi.login(
                    LoginReqeustDto(
                        userId = userId,
                        password = password
                    )
                )
            }.onSuccess {
                // 省略成功逻辑
            }.onFailure { e ->
                _loginError.value = true
                Log.d("LoginViewModel", e.message.toString())
            }
        }
    }

    fun loginError(status: Boolean) {
        _loginError.value = status
    }

    fun autoLogin(status: Boolean) {
        _autoLogin.value = status
    }

    fun hidePassword(status: Boolean) {
        _hidePassword.value = status
    }
}

NetworkModule.kt

@Module
@InstallIn(SingletonComponent::class)
class NetworkModule {

    @Provides
    @Singleton
    fun provideAuthApi(): AuthApi =
        Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create()).build()
            .create(AuthApi::class.java)

    @Provides
    @Singleton
    fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
        return Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .client(okHttpClient)
            .build()
    }

    @Singleton
    @Provides
    fun provideOkHttpClient(
        loggerInterceptor: HttpLoggingInterceptor,
    ): OkHttpClient {
        val okHttpClientBuilder = OkHttpClient().newBuilder()
        okHttpClientBuilder.connectTimeout(60, TimeUnit.SECONDS)
        okHttpClientBuilder.readTimeout(60, TimeUnit.SECONDS)
        okHttpClientBuilder.writeTimeout(60, TimeUnit.SECONDS)
        okHttpClientBuilder.addInterceptor(loggerInterceptor)

        return okHttpClientBuilder.build()
    }

    @Provides
    @Singleton
    fun provideLoggingInterceptor(): HttpLoggingInterceptor =
        HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY }
}

AuthActivity.kt

@AndroidEntryPoint
class AuthActivity : ComponentActivity() {

    private val loginViewModel: LoginViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            val navController = rememberNavController()
            NavHost(
                navController = navController,
                startDestination = NavigationRoute.loginRoute
            ) {
                composable(NavigationRoute.loginRoute) {
                    LoginScreen(
                        loginViewModel = loginViewModel,
                        onNavigateToSignup = { navController.navigate(NavigationRoute.signupRoute) }
                    )
                }
                composable(NavigationRoute.signupRoute) {
                    SignupScreen()
                }
            }
        }
    }
}

解决方案

1. 确保Application类添加@HiltAndroidApp注解

这是Hilt依赖注入系统生效的核心前提,必须在自定义Application类上添加该注解,并在Manifest文件中指定:

@HiltAndroidApp
class NewJeansBunniesApplication : Application() {
    // 自定义Application逻辑
}

在AndroidManifest.xml中配置:

<application
    android:name=".NewJeansBunniesApplication"
    <!-- 其他配置项 -->
>

2. 修复NetworkModule中AuthApi的提供逻辑

当前provideAuthApi方法自行创建了未配置OkHttpClient的Retrofit实例,既存在代码重复也可能引发潜在问题,改为复用已配置好的Retrofit实例:

@Provides
@Singleton
fun provideAuthApi(retrofit: Retrofit): AuthApi =
    retrofit.create(AuthApi::class.java)

3. (可选)在Compose中正确使用hiltViewModel()

如果在Composable函数中获取ViewModel,建议直接使用hiltViewModel()而非从Activity传递,确保Hilt完成正确注入:

composable(NavigationRoute.loginRoute) {
    val loginViewModel: LoginViewModel = hiltViewModel()
    LoginScreen(
        loginViewModel = loginViewModel,
        onNavigateToSignup = { navController.navigate(NavigationRoute.signupRoute) }
    )
}

同时确保添加对应依赖:

implementation "androidx.hilt:hilt-navigation-compose:1.0.0"

内容的提问来源于stack exchange,提问作者HamTory

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 20:46:09