开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 8 天,点击查看活动详情
上次我们讲了如何注入一个interface,注入一个interface必须要在module中提供一个provider方法,现在还有另外一种方法提供一个interface的实例对象,那就是使用@Binds。看看下面的例子。
我们有一个interface:
interface Work {
fun getWorkName():String
}
Interface有两个实例:
class Farmer @Inject constructor():Work {
override fun getWorkName(): String {
return "farmer"
}
}
class Engineer @Inject constructor():Work {
override fun getWorkName(): String {
return "Engineer"
}
}
一个是Framer类,一个是Engineer类,里面又一个getWorkName的方法。如果按照以前的方法方法就需要这样子做:
@Provides
@Named("Farmer")
fun providerFarmer():Work{
return Farmer()
}
在provider的实现里面实例化子类。假设如果Farmer需要传入一个Doing类:
class Doing @Inject constructor() {
fun doingSomething(){
}
}
那么我们provider的方法就要跟踪修改:
@Provides
@Named("Farmer")
fun providerFarmer(doing: Doing):Work{
return Farmer(doing)
}
调用的地方:
Log.i("daggerExample","farmer get my name:${farmer.getWorkName()}")
Log.i("daggerExample","farer what am I do:${farmer.doing.doingSomething()}")
Log.i("daggerExample","engineer get my name:${engineer.getWorkName()}")
这样就会比较麻烦,任何一个参数的修改都会牵扯到provider方法的修改。但是现在如果有了@Binds的方法,就会变的简单很多:
@Binds
@Named("Farmer")
abstract fun bindFarmerWork(farmer: Farmer):Work
@Binds
@Named("Engineer")
abstract fun bindEngineerWork(engineer: Engineer):Work
首先前面当然是要加上@Binds,方法也必须是abstract的,第一个参数是需要实例化的类,这样就完成了。当然Farmer里面传入的参数也必须是要带注解的,要不然也没有办法注入呀。同时还需要注意的是其所在的module也必须是abstract或者变成interface,例如:
@Module
abstract class BindExampleModule {
@Binds
@Named("Farmer")
abstract fun bindFarmerWork(farmer: Farmer):Work
@Binds
@Named("Engineer")
abstract fun bindEngineerWork(engineer: Engineer):Work
}
这里因为返回相同的对象所以需要使用Named进行重命名。
带@Binds的module里面不能再提供provider的方法了,如果同时有就会提示错误:
A @Module may not contain both non-static and abstract binding methods
^
我们看看dagger生成的代码:
private MainActivity injectMainActivity(MainActivity instance) {
MainActivity_MembersInjector.injectFarmer(instance, farmer());
MainActivity_MembersInjector.injectEngineer(instance, new Engineer());
return instance;
}
最终和使用provider的方式是一样的,当然也可以使用scope限定他的作用域了。