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

使用Hilt实现带运行时参数与Repository依赖的ViewModel注入时遇到禁止注入Assisted Factory的错误

使用Hilt实现带运行时参数与Repository依赖的ViewModel注入时遇到禁止注入Assisted Factory的错误

看起来你遇到了Hilt辅助注入ViewModel时的常见坑——直接注入Assisted Factory到ViewModelComponent导致的禁止错误,我来帮你梳理问题和解决办法:

错误原因分析

你收到的错误提示核心是:Hilt不允许在ViewModelComponent中注入ViewModel的Assisted Factory,因为ViewModel的创建必须遵循Android的ViewModelProvider生命周期管理机制,直接从ViewModelComponent获取Factory会破坏ViewModel的生命周期绑定逻辑,而且会导致循环依赖(ViewModel的创建依赖Factory,而Factory又依赖ViewModelComponent)。

你的代码里有两个关键问题:

  • ViewModelFactoryProvider这个EntryPoint被错误地安装在了ViewModelComponent里
  • 你试图在ViewModelModule中手动提供ViewModelProvider.Factory,这完全没必要,Hilt已经帮你处理了Assisted Factory的生成逻辑

正确的实现步骤

1. 保留ViewModel的正确写法(这部分你是对的)

你的ViewModel使用@HiltViewModel(assistedFactory = ...)和@AssistedInject的写法完全符合Hilt规范,不需要修改:

@HiltViewModel(assistedFactory = DetailViewModel.Factory::class)
class DetailViewModel @AssistedInject constructor(
    private val repository: Repository,
    @Assisted itemId: Int
) : ViewModel() {
    // 你的业务逻辑...

    @AssistedFactory
    interface Factory {
        fun create(itemId: Int): DetailViewModel
    }
}

2. 修正EntryPoint的安装组件

把获取Assisted Factory的EntryPoint安装在SingletonComponent(或者ActivityRetainedComponent)里,这样我们可以在Activity/Composable层面提前获取到Factory实例:

@EntryPoint
@InstallIn(SingletonComponent::class)
interface ViewModelFactoryProvider {
    fun detailViewModelFactory(): DetailViewModel.Factory
}

3. 移除ViewModelModule中多余的Factory提供代码

删除ViewModelModule里的provideDetailViewModelFactory方法,因为我们不需要手动创建ViewModelProvider.Factory,而是在使用时动态生成:

@Module
@InstallIn(ViewModelComponent::class)
object ViewModelModule {
    @Provides
    fun provideRepository(listDao: ShoppingListDao,itemDao: ItemDao,storeDao: StoreDao): Repository {
        return Repository(listDao,itemDao,storeDao)
    }
    // 删掉下面这段多余的代码
    // @Provides
    // fun provideDetailViewModelFactory(factory: DetailViewModel.Factory, itemId: Int): ViewModelProvider.Factory {
    //     ...
    // }
}

4. 在Composable中正确创建ViewModel

在Composable里,通过Application上下文获取Assisted Factory,然后动态创建ViewModelProvider.Factory并传入运行时的id参数:

@Composable
fun DetailScreen(
    id: Int,
    navigateUp: () -> Unit
) {
    val applicationContext = LocalContext.current.applicationContext
    // 通过EntryPoint获取Hilt自动生成的Assisted Factory
    val assistedFactory = EntryPointAccessors.fromApplication(
        applicationContext,
        ViewModelFactoryProvider::class.java
    ).detailViewModelFactory()

    // 动态创建ViewModelFactory,传入运行时参数id
    val viewModelFactory = object : ViewModelProvider.Factory {
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            return assistedFactory.create(id) as T
        }
    }

    // 通过viewModel函数绑定ViewModel生命周期
    val viewModel: DetailViewModel = viewModel(factory = viewModelFactory)

    // 你的UI逻辑...
}

为什么这么做?

  • 从SingletonComponent获取Assisted Factory,确保在ViewModel创建之前就能拿到实例,避免了循环依赖
  • 动态创建ViewModelProvider.Factory既可以灵活传入运行时参数,又能保留Hilt对Repository等依赖的自动注入能力
  • 完全遵循Android ViewModel的生命周期管理机制,确保ViewModel在配置变化时不会被意外销毁

备注:内容来源于stack exchange,提问作者Fehru Mandala Putra

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 11:57:58