Dagger Hilt多重绑定不支持List<T>注入报错如何解决
错误原因
核心报错信息如下:
[Dagger/MissingBinding] java.util.List<? extends okhttp3.Interceptor> cannot be provided without an @Provides-annotated method.
这个错误的本质是:Dagger/Hilt 仅内置了Set、Map两种类型的自动多重绑定逻辑,没有默认提供List类型的自动聚合实现,因此框架无法直接识别你要注入的List<Interceptor>依赖,和List本身能不能用没有关系。
不需要强制把多重绑定类型替换为Set,完全可以在保序的前提下解决问题,常用方案有三种:
解决方案
方案1:Set聚合后手动排序转List(最推荐,适配绝大多数场景)
用Hilt原生支持的@IntoSet注解标记所有Interceptor实现,把所有实例自动收集到Set中,再通过@Provides方法把Set转换为排好序的List即可,顺序完全可控。
注意注入Set时需要加@JvmSuppressWildcards注解,避免Kotlin泛型通配符导致的类型不匹配问题(也就是报错里的? extends Interceptor问题)。
代码示例:@Module @InstallIn(SingletonComponent::class) object InterceptorModule { // 标记各个拦截器到Set中 @Provides @IntoSet fun provideHeaderInterceptor(): Interceptor = HeaderInterceptor() @Provides @IntoSet fun provideLoggingInterceptor(): Interceptor = HttpLoggingInterceptor() // 把收集到的Set转为有序List @Provides fun provideInterceptorList( interceptorSet: Set<@JvmSuppressWildcards Interceptor> ): List<Interceptor> { // 自定义排序规则,按业务需要的优先级排序,保证顺序固定 return interceptorSet.sortedBy { interceptor -> when(interceptor) { is HeaderInterceptor -> 0 // 最先执行 is HttpLoggingInterceptor -> 1 // 其次执行 else -> Int.MAX_VALUE // 其他拦截器默认放最后 } } } }后续需要新增拦截器时,只需要新增一个带
@IntoSet的@Provides方法,再把排序规则补上即可,不需要修改List组装的核心逻辑。方案2:手动组装固定顺序List(适合拦截器数量少、变动少的场景)
如果业务里拦截器数量固定,很少新增/调整,完全可以跳过自动多重绑定逻辑,直接在提供OkHttpClient的方法里按顺序手动创建List,顺序100%可控,写法最简单:@Provides @Singleton fun provideOkHttpClient(): OkHttpClient { // 直接按需要的顺序手动添加,顺序完全固定 val interceptors = listOf( HeaderInterceptor(), HttpLoggingInterceptor() ) return OkHttpClient.Builder() .apply { interceptors.forEach { addInterceptor(it) } } .build() }方案3:自定义@IntoList注解实现原生List多重绑定(适合复杂场景)
如果项目里有大量需要注入有序List的场景,可以参考Dagger的@IntoSet实现逻辑,自定义@IntoList注解和对应的绑定处理器,让框架自动支持List类型的多重绑定,不需要手动转Set再排序。这个方案实现成本较高,普通业务场景不推荐使用。
内容的提问来源于stack exchange,提问作者SharePeng Hu

