Hilt是否支持具体化泛型(reified generics)的依赖注入?
Dagger中泛型@Provides方法导致MissingBinding的解决方案
问题出在Dagger的编译时静态分析机制和Kotlin inline reified泛型的特性不兼容:
Dagger需要在编译阶段就明确所有要注入的类型对应的Provider实现,而inline fun <reified T>的泛型类型T是在调用点编译时才确定的,Dagger无法提前扫描到所有可能的T类型,自然没办法为这些类型生成对应的绑定代码,所以会抛出Dagger/MissingBinding错误。
解决方案
根据你的使用场景,有两种可行的精简方式:
1. 针对少量固定类型(如你原来的3个类型)
保留每个具体类型的@Provides方法,但复用一个通用工具函数来避免重复逻辑:
// 通用工具方法,无需添加@Provides注解 inline fun <reified T> createJsonAdapter(moshi: Moshi): JsonAdapter<T> = moshi.adapter() // 每个具体类型的Provider,复用工具方法 @Provides fun provideUserJsonAdapter(moshi: Moshi): JsonAdapter<User> = createJsonAdapter(moshi) @Provides fun provideOrderJsonAdapter(moshi: Moshi): JsonAdapter<Order> = createJsonAdapter(moshi) @Provides fun provideProductJsonAdapter(moshi: Moshi): JsonAdapter<Product> = createJsonAdapter(moshi)
这种方式既减少了重复代码,又完全符合Dagger的编译时要求,不会出现绑定缺失问题。
2. 针对大量类型或动态场景
如果需要注入的JsonAdapter类型很多,可以结合Dagger的Multibindings,把所有Adapter存入Map,在需要的地方按需获取:
首先定义一个MapKey注解:
@MapKey annotation class TypeKey(val value: KClass<*>)
然后编写泛型的Provider方法,将Adapter存入Map:
@Provides @IntoMap @TypeKey(T::class) fun <T : Any> provideJsonAdapter(moshi: Moshi, typeToken: TypeToken<T>): JsonAdapter<T> = moshi.adapter(typeToken.type)
为每个需要的类型提供对应的TypeToken:
@Provides fun userTypeToken(): TypeToken<User> = object : TypeToken<User>() {} @Provides fun orderTypeToken(): TypeToken<Order> = object : TypeToken<Order>() {}
最后在需要注入的类中,通过Map获取对应类型的Adapter:
class MyClass( private val jsonAdapters: Map<Class<*>, @JvmSuppressWildcards JsonAdapter<*>> ) { fun handleUser(json: String) { val userAdapter = jsonAdapters[User::class.java] as JsonAdapter<User> val user = userAdapter.fromJson(json) // ... } }
关键提醒
永远不要在Dagger的@Provides方法中使用inline fun <reified T>,Dagger无法处理这种运行时才确定类型的绑定逻辑,必须让Dagger在编译时就能明确知道每个要注入的具体类型。
内容的提问来源于stack exchange,提问作者Илья Жиленков
相关产品推荐
相关产品推荐

