1.@Binds
使用@Inject
初始化对象时有一种特殊情况:需要初始化的是接口的实例,这时候需要特殊处理一下,就需要用到@Binds
@Module
interface IMainViewModule {
@Binds
abstract fun provideIMainView(main: IMainViewImpl): IMainView
}
这里使用 provideXXX() 方式提供接口实例,说明几点:
- 方法中必须有参数且只能有一个,是接口的实现类
- 实现类必须提供
@Inject
的构造或 Module中@Provides
形式提供 - 方法是抽象方法,不必写方法体
- 使用
@Binds
代替@Provides
- 由于方法是抽象的,所以类也要抽象或接口
IMainViewImpl.kt 的代码:
class IMainViewImpl @Inject constructor() : IMainView
2.@IntoSet
使用注入形式初始化 Set 集合时,可以在 Module 中多次定义一系列返回值类型相同的方法:
@Module
class AnimalModule {
@IntoSet
@Provides
fun provideElephant() = Animal("大象")
@Provides
@IntoSet
fun provideMonkey() = Animal("猴子")
}
Animal.kt 代码:
class Animal(var name: String)
上面的 provideElephant() 和 provideMonkey() 返回值类型都是 Animal,都使用了@IntoSet
注释,多说一句,@Provides
当然也要有,如果是接口用@Binds
。
初始化并使用:
@Inject
lateinit var set: MutableSet<Animal>
...//代码省略
set.forEach {
Log.i("Main", "--- ${it.name} ---")
}
kotlin 里面 MutableSet 代替 Java 中的 Set,上面代码运行可以输出:
--- 大象 ---
--- 猴子 ---
3.@IntoMap
与@IntoSet
区别不大,Map 多了一个 key
@Provides
@IntoMap
@IntKey(0)
fun provideFish() = Animal("鱼")
@Provides
@IntoMap
@IntKey(1)
fun provideHuman() = Animal("人")
@IntKey
里面就是 Map 中的 key,providesXXX() 返回值是 key 对应的 value,如果 key 是 String 类型的,则使用@StringKey()
输入 key,此外,还可以自定义 key:
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@MapKey
annotation class ZhuangBiKey(val f: Float)
初始化 map 并使用:
@Inject
lateinit var map: Map<Int, Animal>
...//代码省略
map.forEach {
Log.i("Main", "--- key:${it.key}\nvalue:${it.value.name} ---")
}
最后,说实话我觉得这样初始化一个 Set 或者 Map 效率不高,只不过为了别人这样写我们能看懂而已。其实我觉得整个 dagger2 都不咋地(发布时删掉这句)。
其他几篇的链接:
Dagger2 中的 Qualifier
Dagger2 中的 Scope、dependencies
Dagger2 中的 SubComponent
Dagger2 中使用 AndroidInjection 优化注入流程