前言
Dagger2 已经出来挺久了,网上相关的教程也很多,普遍都说它比较难上手。
相比起其他框架确实如此,但只要学习后加以实践,还是比较好明白的,说不定你还会从此对它爱不释手。
推荐阅读:
1. 什么是Dagger2
Dagger2 是一个依赖注入(Dependency Injection)框架。
2. 使用Dagger2有什么好处
-
解耦
假设有一个A类,项目中很多地方都使用到它(在很多地方通过new A()对A实例进行了初始化)。然后由于需求变动,A的构造函数增加了一个参数。
好了,牵一发而动全身,你需要把各个new A()的地方都进行修改。
但如果是使用Dagger2进行管理,你只需在类实例的供应端进行修改即可。 -
让功能实现更专注于功能实现
假设现在你需要调用A类的x()方法来实现某功能,但是A类的构造过程相当的复杂(这样的例子可以参考GreenDao中获取XXXDao、Retrofit中获取Observable请求)
public void xxx(){
E e = new E();
D d = new D(e);
C c = new C();
B b = new B(c,d);
A a = new A(b);
a.x();
}
结果6行代码中,构造实例a占了5行,调用x()方法实现功能却只占了1行。
但如果使用Dagger2进行管理,将a实例的构造过程移至实例供应端,则功能实现模块的代码会变成这样
@Injcet
A a;
public void xxx(){
a.x();
}
这就是所说的让功能实现更专注于功能实现,而不必去管a实例的构造过程。
- 更好地管理类实例
通常我们开发中会有两种类实例:- 一种是全局实例(单例),它们的生命周期与app保持一致。
- 一种是页面实例,它们的生命周期与页面保持一致。
- 通过Dagger2,我们可以使用一个组件专门管理全局类实例(也免去了单例的写法,不用考虑饿汉懒汉什么的);然后各个页面也有各自组件去管理它们的页面实例。
- 这样不管是对于实例的管理,还是项目的结构,都会变得更加的清晰明了。
使用
1. 添加依赖
compile 'com.google.dagger:dagger:2.14.1'
annotationProcessor 'com.google.dagger:dagger-compiler:2.14.1'
2. 处理实例需求端
在实例需求端中,使用@Inject标注需要注入的实例变量。
public class UploadActivity extends AppCompatActivity{
@Inject
UploadPresenter mPresenter;
}
3. 处理实例供应端
- 方式一:使用 Module
@Module
public class UploadActivityModule {
@Provides
UploadPresenter uploadPresenter() {
return new UploadPresenter();
}
}
- 方式二:使用@Inject标注构造函数
public class UploadPresenter{
@Inject
public UploadPresenter() {
}
}
注意: 方式一的优先级高于方式二,意思就是:
- 在供应某实例时,会先通过方式一查找是否存在返回该实例的的方法
- 如果存在,则获取实例并对外供应
- 如果不存在,再通过方式二查找是否存在@Inject标注的构造函数
- 如果存在,则将通过该构造函数构造实例并对外供应
- 如果不存在,那将报错,因为无法供应所需的实例
4. 搭建桥梁
- 使用@Component标注接口,表示它为桥梁。
(如果使用1.3.1的方式供应实例,则需在@Component(modules=xxx.class)中指明module。)
一个Component可以没有module,也可以同时有多个module。 - 添加 void inject(实例需求端) 方法,表明实例供应端中的实例将交给该实例需求端。
通过这个方法,查找实例需求端中需要注入的实例有哪些(使用@Inject标注的那些实例),然后在实例供应端中获取所需的实例,最后注入到实例需求端中 - 用来注入的方法,它的方法名不一定要是inject,可以随便取,一般都取inject。但该方法的返回类型必须为void
@Component(modules = UploadActivityModule.class)
public interface UploadActivityComponent {
void inject(UploadActivity uploadActivity);
}
5. 编译,注入
- 完成以上几步后,ReBuild一下项目以生成DaggerUploadActivityComponent类。
- 在实例需求端中调用inject完成实例的注入
public class UploadActivity extends AppCompatActivity{
@Inject
UploadPresenter mPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//注入实例
DaggerUploadActivityComponent.builder()
.build()
.inject(this);
//注入后即可调用mPresenter中的方法了
mPresenter.xxx();
}
}