最近看github的时候,看到很多项目都已经用到Dagger 2了。现在Dagger 2已经有Google开始维护了,相信Dagger 2在Android中的应用将会越来越广泛。觉得有必要好好学习一下Dagger 2。
什么是Dagger
Dagger是android的一个依赖注入框架,有别于其他的依赖注入框架使用的反射机制,Dagger是利用编译时生成辅助类的方式来完成调用,所以效率有了很大的提升,非常适合用于Android开发。Google从square那儿接手了Dagger之后,号称将Dagger的效率又提升了13%。
Dagger 注释
从注释开始学习最直观。一般Dagger中
常用的注释有:
@Inject:
Dagger使用的是
javax.inject.Inject。主要作用有:
1.修饰变量,表示这个变量为需要注入的依赖。
@Inject
EmployeePresenter employeePresenter;
2.修饰构造函数,表示如果这个类有需要被注入依赖时,Dagger会调用这个构造函数来进行实例化。
@Inject
public EmployeePresenter() {
Log.d(TAG, "EmployeePresenter() called!");
}
那么问题来了,什么时候通知Dagger开始注入呢?这个就保留到@Component中讲。
@Module:
用来修饰类,表示此类的方法是用来提供依赖的。
@Module
public class UserModule {
@Provides
@Type("coder")
Employee createCoder() {
return new Employee("coder");
}
@Provides
@Type("boss")
Employee createBoss() {
return new Employee("boss");
}
}
此处的@Type注释,请看@Qualifier
@Provides
只能用来修饰Module类中的方法,用来提供依赖的实例。在这个方法中,我们可以自定义这个依赖的实例化的方式。这也是@Inject的一种补充,因为很多时候我们没办法使用@Inject,如:interface没有构造函数,自然不能使用@Inject,又或者比如 Activity的构造函数是封装好的,我们不能改变,所以也不能用@inject
@Component
修饰接口,起到注入器的作用,是@Inject和@Module之间的桥梁。提供所有你定义类型的实例。
@Component(modules = {UserModule.class})
public interface UserComponent {
void inject(UserListActivity activity);
@Type("coder")
Employee createCoder();
@Type("boss")
Employee createBoss();
}
此处的@Type注释,请看@Qualifier
这是MainActivity中的部分代码
private UserComponent userComponent;
@Inject
EmployeePresenter employeePresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initializeInjectors();
}
private void initializeInjectors() {
userComponent = DaggerUserComponent.builder().userModule(new UserModule()).build();//DaggerUserComponent就是Dagger在编译时自动生成的一个UserComponent的实现。
// userComponent = DaggerUserComponent.create(); //在Component中的Module都是默认的构造函数是,也可以使用create()来简化实例化的代码。
userComponent.inject(this); //就是在这里通知Dagger去实例化需要注入的依赖的
}
@Scope
在Dagger中,依赖只有singleton和非singleton之分。@Singleton标记是用于Application-Lever的单例。自定义的scope用于生命周期更短的依赖,如:@PerActivity表示生命周期跟Activity一样,但这只是语义上的标记而已,实际的生命周期管理还需要代码控制。
@Qualifier
当类的类型不足以区分依赖时,就要使用这个标记了。比如,你需要注入两个String类型的实例:userName(), userTitle()。这个时候 Dagger就没有办法区分了,所以就要用到@Qualifier来进一步区分。
@Module
public class UserModule {
@Provides
// @Type("coder")
Employee createCoder() {
return new Employee("coder");
}
@Provides
// @Type("boss")
Employee createBoss() {
return new Employee("boss");
}
}
@Component(modules = {UserModule.class})
public interface UserComponent {
void inject(MainActivity activity);
// @Type("coder")
Employee createCoder();
// @Type("boss")
Employee createBoss();
}
要解决这个错误就要使用@Qualifier。
@Qualifier
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Type {
String value() default "";
}
这样就自定义了一个注释Type,用来区分以上Coder,Boss的问题。
分别在Component和Module中,对应加上@Typ("coder"),@Type("Boss"),Dagger就可以识别匹配了。