从Dagger2迁移到Hilt:如何迁移带自定义Component.Factory的应用组件
Dagger2 迁移 Hilt:ApplicationComponent.Factory 处理方案
问题背景
将遗留应用从Dagger2迁移到Hilt时,原ApplicationComponent通过Factory绑定多个实例并依赖子组件,转为EntryPoint后无法处理Factory中的额外内容,具体代码如下:
原ApplicationComponent代码
abstract class ApplicationComponent : ApplicationDependencies { abstract fun inject(application: MyApp) @Component.Factory interface Factory { fun applicationComponent( @BindsInstance myApp: MyApp, @BindsInstance sharedPreferences: SharedPreferences, @BindsInstance activeActivityProvider: ActiveActivityProvider, @BindsInstance appLifecycleObservable: Observable<ApplicationStateEvent>, @BindsInstance @EnvironmentName environmentName: String, schedulersComponent: SchedulerComponent, commonComponent: CommonComponent, ): ApplicationComponent } }
原MyApp初始化代码
public class MyApp extends Application { private ApplicationComponent component; // ... 定义 appLifecyleObserver 等逻辑 public void onCreate() { ProcessLifecycleOwner.get().getLifecycle().addObserver(appLifecycleObserver); super.onCreate(); // ... 初始化 mSharedPreferences、environmentName 等逻辑 component = DaggerApplicationComponent.factory().applicationComponent( this, mSharedPreferences, activeActivityProvider, appLifecycleRelay, environmentName, DaggerSchedulersComponent.create(), DaggerCommonComponent.factory().commonComponent(this), ); component.inject(this); } }
迁移方案
Hilt没有直接对应Dagger Component.Factory的概念,需将Factory中的参数拆分处理:
处理@BindsInstance绑定的实例
MyApp实例:在MyApp上添加@HiltAndroidApp注解,Hilt自动绑定Application/MyApp类型,无需手动传入。- 其余绑定实例(
SharedPreferences、ActiveActivityProvider等):创建Hilt单例模块,通过@Provides方法提供实例,复用原初始化逻辑:@Module @InstallIn(SingletonComponent::class) object AppBindingsModule { @Provides @Singleton fun provideSharedPreferences(app: MyApp): SharedPreferences { // 复用原代码中初始化mSharedPreferences的逻辑 return app.getSharedPreferences("app_prefs", Context.MODE_PRIVATE) } @Provides @Singleton @EnvironmentName fun provideEnvironmentName(app: MyApp): String { // 复用原代码中获取environmentName的逻辑 return app.environmentName } @Provides @Singleton fun provideActiveActivityProvider(): ActiveActivityProvider { // 原代码中初始化该实例的逻辑 return ActiveActivityProviderImpl() } @Provides @Singleton fun provideAppLifecycleObservable(app: MyApp): Observable<ApplicationStateEvent> { // 复用原appLifecycleRelay的逻辑 return app.appLifecycleRelay } }
处理依赖的子组件(SchedulerComponent、CommonComponent)
- 将子组件转为Hilt模块,把原组件提供的依赖移到
@InstallIn(SingletonComponent::class)的模块中:- 无依赖的
SchedulerComponent:直接在模块中提供对应依赖 - 依赖
MyApp的CommonComponent:在@Provides方法中注入MyApp复用逻辑
示例:
@Module @InstallIn(SingletonComponent::class) object CommonModule { @Provides @Singleton fun provideCommonDependency(app: MyApp): CommonDependency { // 复用原CommonComponent中提供该依赖的逻辑 return CommonDependencyImpl(app) } } - 无依赖的
- 将子组件转为Hilt模块,把原组件提供的依赖移到
替换原Component注入逻辑
- 在
MyApp上添加@HiltAndroidApp注解,Hilt自动生成SingletonComponent替代原ApplicationComponent - 移除原
component变量及手动初始化代码,Hilt自动完成注入;若需在MyApp中获取依赖,定义EntryPoint:@HiltAndroidApp public class MyApp extends Application { // ... 保留appLifecyleObserver等逻辑 @Override public void onCreate() { ProcessLifecycleOwner.get().getLifecycle().addObserver(appLifecycleObserver); super.onCreate(); // 移除原component初始化代码 } // 定义EntryPoint用于获取依赖 @EntryPoint @InstallIn(SingletonComponent.class) interface AppEntryPoint { SharedPreferences getSharedPreferences(); // 其他需要暴露的依赖 } }
- 在
替换原inject方法
原ApplicationComponent的inject(MyApp)方法无需保留,只需在MyApp中需要注入的字段上添加@Inject注解,Hilt自动完成注入。
内容的提问来源于stack exchange,提问作者Jenny Zeng
相关产品推荐
相关产品推荐

