Dagger2 中创建实例对象有两种方式:
- Inject 维度:通过用 Inject 注解构造函数
- Module 维度:通过工厂模式的 Module 创建
其中,Module 的优先级比 Inject 高。基于同样维度的不同实例,比如
@Inject A(){}
和@Inject A(B b){}
,系统就会抱错,这种情况叫做依赖注入迷失。
Qualifier
限定符 就是解决依赖注入迷失的。
1.定义限定符注解
- java 中的方式:
@Qualifier
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Named {
String name() default "";
}
- kotlin 中的方式:
@Qualifier
@Documented
@Retention(RetentionPolicy.RUNTIME)
annotation class Named(val name: String)
2.Module 中使用
@Provides
@Named("dog")
@Singleton
fun providesAnimal(): Dog {
Log.e("abc", "----- dog -----")
return Dog()
}
@Provides
@Named("dog2")
@Singleton
fun providesAnimal2(): Dog {
Log.e("abc", "----- dog2 -----")
return Dog()
}
3.实例化
@Inject
@field:Named("dog")
lateinit var dog: Dog
@Inject
@field:Named("dog2")
lateinit var dog2: Dog
根据打印的内容可以知道,创建对象 dog 和 dog2 的时候分别调用了 providesAnimal() 和 providesAnimal2()。
说明:如果用@Named("xx")
代替@field:Named("xx")
会报错,因为代码编译为 Java 字节码的时候会对应三个目标元素:一个是变量本身、还有 getter 和 setter,Kotlin 不知道这个变量的注解应该使用到哪个目标上。使用 field 关键字是告诉 Kotlin 所注解的目标是哪个。
最后
项目源码
其他几篇的链接:
Dagger2 中的 SubComponent
Dagger2 中的 Scope、dependencies
Dagger2 中使用 AndroidInjection 优化注入流程
Dagger2 中的 Binds、IntoSet、IntoMap