目录
0. 前言
1. 依赖与注入
2. @Inject
3. @Module & @Provides
4. @Component
5. @Qualifier
6. Provider & Lazy
7. @Scope
8. 注入到Set和Map容器
9. Bind系列注解
10. dagger中依赖关系与继承关系
11. dagger.android
目标
本篇文章的目标是介绍dagger中Bind家族相关的注解,有@Binds
、@BindsOptionalOf
、@MultiBinds
、@BindsInstance
@Binds
之前我们一直没有为CPU
创建CPUMoudle
,因为我们将@Inject
注解到其构造函数上了,dagger就会自动生成CPU_Factory
工厂类,当有其他对象需要依赖CPU
时,直接调用此工厂类去创建而不用在@Component.modules
中声明类似于CPUModule
的依赖,但如果这种情况发生在具有**抽象(继承)**关系的对象上呢?比如我们知道CPU
厂商有Intel
和AMD
两家,虽然我们可以将@Inject
都注解到其各自的构造函数上:
open class CPU {
private val id = Random.nextInt()
open fun execute(builder: StringBuilder) {
// CPU执行时返回自身序列号信息
builder.append("CPU Id: ").append(id).append("\n")
}
}
class Intel @Inject constructor() : CPU() {
override fun execute(builder: StringBuilder) {
builder.append("Intel's ")
super.execute(builder)
}
}
class AMD @Inject constructor() : CPU() {
override fun execute(builder: StringBuilder) {
builder.append("AMD's ")
super.execute(builder)
}
}
但我们在需要依赖注入的地方(例如Computer
和CaseActivityComponent
中)就不能使用其父类CPU
作为需要依赖的声明了:
// 下面这两种声明在dagger编译时都会出错,因为dagger并不知道这里需要的是CPU的哪一个实现类
@set:Inject lateinit var cpu: CPU
fun getCPU(): CPU
解决方案我想大家心里都有数,一是将上述代码中的CPU
改为Intel
或AMD
,但这样就违反了依赖倒置原则;二是通过@Module
+@Provides
的方法,也许还要用上@Qualifier
指定类型别名,这种方案可以解决问题,但这种情况下dagger提供了另一种解决方案——使用@Binds
注解:
// 这种情况避免不了创建CPUModule,注意下面是抽象类和抽象方法
@Module
abstract class IntelCPUModule {
@Binds abstract fun bindIntelCPU(cpu: Intel): CPU // 注意这里的入参
}
@Module
abstract class AMDCPUModule {
@Binds abstract fun bindIntelCPU(cpu: AMD): CPU
}
// 使用到的地方需要声明@Component.modules依赖上述Module
@Component(modules = [MemoryModule::class, DiskModule::class, DeviceModule::class, IntelCPUModule::class])
interface ComputerComponent {
/* ... */ }
@Component(modules = [ComputerModule::class, TimestampModule::class, MonitorModule::class, AMDCPUModule::class])
interface CaseActivityComponent {
/* ... */ }
@Module
+@Binds
方案比起@Mo