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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 22:45:29