Hilt:如何基于参数通过@AssistedInject注入对象
Hilt + AssistedInject 动态注入接口实现的最佳实践
你当前的实现问题在于:手动在ViewModel里实例化Implementation会丢失Hilt对其依赖(比如Repository)的注入能力,而且硬编码的when逻辑不够优雅。关于是否能不用键值直接注入目标对象——无法完全省略标识,但可以通过Hilt的特性优化实现,避免手动判断实例化。
以下是几种最佳实践方案:
方案1:多绑定Map + 辅助注入key
通过Hilt的多绑定功能,将所有SomeInterface实现绑定到一个Map<String, SomeInterface>,结合@AssistedInject传入的key动态获取实例,替代手动when判断。
步骤1:绑定实现到Map
@Module @InstallIn(SingletonComponent::class) object SomeInterfaceModule { @Provides @IntoMap @StringKey("Example") fun provideExampleImpl(impl: Implementation): SomeInterface = impl @Provides @IntoMap @StringKey("Other") fun provideOtherImpl(impl: OtherImplementation): SomeInterface = impl }
步骤2:ViewModel中注入Map并通过key获取实例
class Test @AssistedInject constructor( @Assisted private val key: String, private val someInterfaceMap: Map<String, @JvmSuppressWildcards SomeInterface> ): ViewModel() { val someInterface: SomeInterface = checkNotNull(someInterfaceMap[key]) { "找不到对应key的实现:$key" } }
步骤3:AssistedFactory定义
@AssistedFactory interface TestViewModelFactory { fun create(key: String): Test }
方案2:限定符+专用ViewModel/工厂方法
如果不需要动态切换实现,而是在创建ViewModel时就确定要使用的实现,可以用限定符标记不同实现,直接注入到ViewModel中,完全不用key。
步骤1:定义限定符
@Qualifier @Retention(AnnotationRetention.BINARY) annotation class ExampleImpl @Qualifier @Retention(AnnotationRetention.BINARY) annotation class OtherImpl
步骤2:绑定带限定符的实现
@Module @InstallIn(SingletonComponent::class) interface SomeInterfaceBindModule { @ExampleImpl @Binds fun bindExampleImpl(impl: Implementation): SomeInterface @OtherImpl @Binds fun bindOtherImpl(impl: OtherImplementation): SomeInterface }
步骤3:直接注入带限定符的实现
可以创建专用ViewModel子类:
// 基础ViewModel abstract class BaseTestViewModel(open val someInterface: SomeInterface): ViewModel() // 对应Example实现的ViewModel class ExampleTestViewModel @AssistedInject constructor( @ExampleImpl override val someInterface: SomeInterface ): BaseTestViewModel(someInterface) // 对应Other实现的ViewModel class OtherTestViewModel @AssistedInject constructor( @OtherImpl override val someInterface: SomeInterface ): BaseTestViewModel(someInterface)
或者在工厂中定义不同的创建方法:
@AssistedFactory interface TestViewModelFactory { fun createExampleVM(): ExampleTestViewModel fun createOtherVM(): OtherTestViewModel }
核心原则
- 永远不要在ViewModel内部手动实例化依赖,必须由Hilt提供,保证依赖注入的完整性。
- 用限定符区分同一接口的不同实现,让Hilt明确注入目标。
- 动态选择场景用多绑定Map,避免硬编码判断;固定实现场景直接用限定符注入,完全省略key。
内容的提问来源于stack exchange,提问作者android dev
相关产品推荐
相关产品推荐

