Hilt迁移:如何为Dagger 2依赖提供Hilt SingletonComponent?
现有Dagger 2组件代码如下:
@Component(modules = [FragmentAModule::class], dependencies = [AppComponent::class]) @ViewScope interface FragmentAComponent { fun inject(fragment: FragmentA) }
Fragment中的注入逻辑:
DaggerFragmentAComponent.builder() .appComponent(App.appComponent()) .build() .inject(this)
目前正在从Dagger 2迁移到Hilt,无法一次性完成全量迁移,计划先迁移应用级单例,需要替换dependencies = [AppComponent::class]和appComponent(App.appComponent())部分,希望了解如何在Dagger 2代码中使用Hilt的SingletonComponent。
可以通过以下两种方式让Dagger 2组件对接Hilt的SingletonComponent:
方式一:直接依赖Hilt的SingletonComponent
1. 修改Dagger组件声明
将原有的AppComponent依赖替换为Hilt自动生成的SingletonComponent,保留原模块和自定义作用域:
@Component(modules = [FragmentAModule::class], dependencies = [SingletonComponent::class]) @ViewScope interface FragmentAComponent { fun inject(fragment: FragmentA) }
前提:项目已正确配置Hilt依赖,且Application类添加了
@HiltAndroidApp注解。
2. 更新Fragment注入代码
不再手动获取AppComponent,改为通过Hilt的Application实例获取SingletonComponent:
DaggerFragmentAComponent.builder() .singletonComponent((requireContext().applicationContext as YourHiltApp).singletonComponent) .build() .inject(this)
这里YourHiltApp是你添加了@HiltAndroidApp注解的Application类。
方式二:使用EntryPoint按需获取依赖(推荐)
如果不需要让Dagger组件直接依赖整个SingletonComponent,仅需其中部分依赖,推荐用Hilt的EntryPoint机制,更符合模块化设计:
1. 定义EntryPoint接口
声明Dagger组件需要的Hilt单例依赖:
@EntryPoint @InstallIn(SingletonComponent::class) interface FragmentADeps { // 列出FragmentAComponent需要的所有单例依赖,例如: fun provideUserRepository(): UserRepository fun provideApiService(): ApiService }
2. 修改Dagger组件与模块
移除组件对AppComponent的依赖,改为通过模块接收EntryPoint实例:
@Component(modules = [FragmentAModule::class]) @ViewScope interface FragmentAComponent { fun inject(fragment: FragmentA) // 定义工厂方法,用于传入EntryPoint fun factory(): Factory interface Factory { fun create(fragmentADeps: FragmentADeps): FragmentAComponent } }
在模块中通过EntryPoint获取需要的依赖:
@Module class FragmentAModule { @Provides @ViewScope fun provideFragmentViewModel( userRepo: UserRepository, apiService: ApiService ): FragmentAViewModel { return FragmentAViewModel(userRepo, apiService) } }
3. 更新Fragment注入代码
通过Hilt的EntryPointAccessors获取EntryPoint实例,再创建Dagger组件:
val fragmentADeps = EntryPointAccessors.fromApplication( requireContext().applicationContext, FragmentADeps::class.java ) DaggerFragmentAComponent.factory() .create(fragmentADeps) .inject(this)
注意事项
- 确保Hilt配置完整:根build.gradle添加Hilt插件,app模块添加Hilt依赖与注解处理器。
- 自定义的
@ViewScope需正确标注@Scope和@Retention(RUNTIME),避免与Hilt内置作用域冲突。 - 迁移期间,同一类单例仅由Hilt管理,避免Dagger和Hilt重复提供实例。
内容的提问来源于stack exchange,提问作者mooongcle

