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

自定义ViewModelStoreOwner创建HiltViewModel崩溃的排查与解决

问题描述

我有一段可正常运行的Compose代码:

val pagerVM = hiltViewModel(
    creationCallback = { factory: JourneySummaryPagerViewModel.Factory ->
        factory.create(selectedIndex.value)
    },
    key = viewModel.journeys.toString()
)
JourneySummaryPager(
    viewModel = pagerVM
)

出于项目需求,我需要将ViewModel的生成限定在特定的ViewModelStoreOwner范围内,因此编写了如下代码:

val storeOwner = object : ViewModelStoreOwner {
    override val viewModelStore = ViewModelStore()
}

CompositionLocalProvider(value = LocalViewModelStoreOwner provides storeOwner) {

    val pagerVM = hiltViewModel(
        creationCallback = { factory: JourneySummaryPagerViewModel.Factory ->
            factory.create(selectedIndex.value)
        },
        key = viewModel.journeys.toString()
    )
    JourneySummaryPager(
        viewModel = pagerVM
    )
}

但启动应用时出现崩溃,报错信息如下:

java.lang.RuntimeException: Cannot create an instance of class
fr.tisseo.android.screen.map.header.journey.journeySummaryPager.JourneySummaryPagerViewModel
at
androidx.lifecycle.viewmodel.internal.JvmViewModelProviders.createViewModel(JvmViewModelProviders.kt:40)

请问如何让Hilt能够通过自定义ViewModelStoreOwner创建我的ViewModel?

解决方案

崩溃的核心原因是自定义的ViewModelStoreOwner没有关联Hilt的依赖注入上下文,Hilt无法在这个自定义实例中获取ViewModel所需的依赖与Factory。解决步骤如下:

  1. 定义Hilt EntryPoint获取ViewModelFactory
    先创建一个EntryPoint接口,用于从Hilt组件中获取ViewModelFactory:

    @InstallIn(SingletonComponent::class) // 根据你的实际依赖范围调整,比如ActivityComponent/FragmentComponent
    @EntryPoint
    interface ViewModelFactoryEntryPoint {
        fun viewModelFactory(): ViewModelProvider.Factory
    }
    
  2. 实现带Hilt支持的自定义ViewModelStoreOwner
    让自定义的ViewModelStoreOwner同时实现HasDefaultViewModelProviderFactory接口,绑定Hilt提供的ViewModelFactory:

    // 从当前应用上下文获取Hilt EntryPoint
    val entryPoint = EntryPointAccessors.fromApplication(
        LocalContext.current.applicationContext,
        ViewModelFactoryEntryPoint::class.java
    )
    val hiltViewModelFactory = entryPoint.viewModelFactory()
    
    val storeOwner = object : ViewModelStoreOwner, HasDefaultViewModelProviderFactory {
        override val viewModelStore = ViewModelStore()
        override val defaultViewModelProviderFactory: ViewModelProvider.Factory
            get() = hiltViewModelFactory
    }
    
  3. 保持原有调用逻辑即可
    现在在CompositionLocalProvider内部调用hiltViewModel时,就能通过自定义storeOwner的Hilt Factory正确创建ViewModel:

    CompositionLocalProvider(value = LocalViewModelStoreOwner provides storeOwner) {
        val pagerVM = hiltViewModel(
            creationCallback = { factory: JourneySummaryPagerViewModel.Factory ->
                factory.create(selectedIndex.value)
            },
            key = viewModel.journeys.toString()
        )
        JourneySummaryPager(viewModel = pagerVM)
    }
    

额外注意事项

  • 确保JourneySummaryPagerViewModel及其Factory是由Hilt管理的(比如使用@HiltViewModel注解,Factory由Hilt自动生成)
  • 自定义的ViewModelStoreOwner需要在合适的时机调用viewModelStore.clear(),避免内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 11:50:12