开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 6 天,点击查看活动详情
上次我们简单认识了dagger2,并做了简单的使用,上次我们注入的是一个简单的类,这次我们讲解一下,如何注入一个interface。我们先来按照上次的写法来注入一个interface。
interface Person {
fun getSex():Int
}
再写一个实现:
class Man: Person {
override fun getSex(): Int {
return 0
}
}
那我们注入的时候是需要在interface上面注入还是在实现类上面注入呢?
我们现在Man上写一个注入:
class Man @Inject constructor():Person {
override fun getSex(): Int {
return 0
}
}
然后在MainActivity中注入这个对象:
@Inject
lateinit var man: Man
man.getSex().let {
Log.i("dagger2example","gender is :$it")
}
打印:
I/dagger2example: gender is :0
这样注入是可以的。那问题又来了,如果我不想用他们的子类,我想注入Person怎么办?就如这个样子:
@Inject
lateinit var person: Person
这样能注入进来吗? 看看编译:
error: Person cannot be provided without an @Provides-annotated method.
public abstract interface ExampleComponent {
^
com.xxx.dagger2example.Person is injected at
com.xxx.dagger2example.MainActivity.person
com.xxx.dagger2example.MainActivity is injected at
com.xxx.dagger2example.ExampleComponent.inject(com.xxx.dagger2example.MainActivity)
所以就是因为是interface,没有办法直接注入到对象里面,他需要在component里面提供一个provider方法去指明需要实现哪一个类。那我们就需要指明需要实例哪一个对象。
这里我们需要引入Dagger2的另外一个概念即Module,如果要provider一个对象,就需要在Module里面去添加,使用@Provider关键字,这个关键字只能在Module中使用,所以定义Module如下:
@Module
class ExampleModule {
@Provides
fun providerPerson():Person{
return Man()
}
}
要使成为module则必须类前面加@Module关键字。providerPerson方法的名字无所谓,只要返回的对象对应就行,但是如果有两个方法返回相同的对象那就会出错,例如:
@Module
class ExampleModule {
@Provides
fun providerMan():Person{
return Man()
}
@Provides
fun providerWoman():Person{
return Woman()
}
}
编译会报错:
Person is bound multiple times:
就会告诉你这个对象被绑定了2次。那如何我们就是有需求要返回两次的该怎么办呢?可以用起别名的方式来解决这个问题,在Module中使用:
@Module
class ExampleModule {
@Provides
@Named("Man")
fun providerMan():Person{
return Man()
}
@Provides
@Named("Woman")
fun providerWoman():Person{
return Woman()
}
}
用@Named关键字区分,在使用的地方:
@Inject
@Named("Woman")
lateinit var person: Person
还是使用@Named来区分到底使用哪一个对象。这样再运行:
gender is :1