dagger2
dagger2是一种依赖注入框架,由square开发,现在google负责维护。dagger2一般配合mvp,在mvp已经解耦的基础上,让解耦变得更彻底,以便于测试及维护。
dagger2与dagger的区别
- 再也没有使用反射:图的验证、配置和预先设置都在编译的时候执行。
- 容易调试和可跟踪:完全具体地调用提供和创建的堆栈
- 更好的性能:谷歌声称他们提高了13%的处理性能
- 代码混淆:使用派遣方法,就如同自己写的代码一样
当然所有这些很棒的特点都需要付出一个代价,那就是缺乏灵活性,例如:Dagger2没用反射所以没有动态机制。
注解含义
@Inject
: 通常在需要依赖的地方使用这个注解,标识我们需要的实例。另外在@Provide
中,直接返回的实例,需要在类的构造函数添加@Inject
@Module
: 我们定义一个类,用@Module注
解,Modules
类里面的方法专门提供依赖。这样Dagger
在构造类的实例的时候,就知道从哪里去找到需要的依赖。modules的一个重要特征是它们设计为分区并组合在一起(比如说,在我们的Component中可以有多个组成在一起的modules)。@Provide
: 在Modules
类中,我们定义的方法是用这个注解。这些方法都是用来提供依赖,生成实例的。@Singlton
:常用在@Provide
之前,表示提供的依赖是个单例,也就是每次都提供同一个实体。@Component
: 我们定义一个接口,用Components
注解,我们可以理解为Component就是一个注入器,是@Inject和@Module的桥梁。它的主要作用就是连接这两个部分。 Components可以提供所有定义了的类型的实例,比如:我们必须用@Component注解一个接口然后列出所有的@Modules组成该组件,如果缺失了任何一块都会在编译的时候报错。所有的组件都可以通过它的Modules
知道依赖的范围。@Scope
: Dagger2可以通过自定义注解限定注解作用域。后面会演示一个例子,这是一个非常强大的特点,因为就如前面说的一样,没 必要让每个对象都去了解如何管理他们的实例。在scope的例子中,我们用自定义的@PerActivity注解一个类,所以这个对象存活时间就和 activity的一样。简单来说就是我们可以定义所有范围的粒度(@PerFragment, @PerUser, 等等)。Qualifier
: 当类的类型不足以鉴别一个依赖的时候,我们就可以使用这个注解标示。例如:在Android中,我们会需要不同类型的context,所以我们就可以定义 qualifier注解“@ForApplication”和“@ForActivity”,这样当注入一个context的时候,我们就可以告诉 Dagger我们想要哪种类型的context。
引入工程
在app/build.gradle添加依赖
1 | apply plugin:'android-apt' |
因为Dragger2是基于注解的,它会预先生成一些类文件,所以需要在整个项目的/build.gradle文件中加上apt工具:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19buildscript {
repositories {
jcenter()
}
dependencies {
...
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
allprojects {
repositories {
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
demo详解
我们通过使用greenDao的示例来说明,引入dagger2的好处。greenDao是非常流行的管理sqldata的orm,我们希望他以单例的形式存在,生命周期等同于Application。
首先,创建GreenDaoModule.java
GreenDaoModule.java
1 | @Module |
在上述代码中,我们提供了BaseApp,SQLiteDatabase,DaoMaster,DaoSession的依赖,均是单例模式。
在目标类注解的时候,会在GreenDaoModule寻找依赖并提供实例。
创建AppComponent.java,提供注射器
我们新建一个interface,添加@Component注解,就提供了一个注射器,桥接@Inject跟@Module。
AppComponent.java1
2
3
4
5
6
7
8@Singleton
@Component(modules = {GreenDaoModule.class})
public interface AppComponent {
BaseApp getApplication();
BasePresenter inject(BasePresenter basePresenter);
}
其中BasePresenter是注射目标,也就是说想要在哪个类里面使用依赖注解,必须在component中注射。
比如我们想在BasePresenter这个类里,使用依赖注入DaoSession实例,必须在component里插入。
在Application中交给dagger2来完成初始化
Dagger会处理我们的注解,为components生成实现并重命名加上“Dagger”前缀。
MyApplication.java1
2
3
4
5
6
7
8
9
10
11
12
13
14/**
* 初始化依赖加载器
*/
private void initInjector(){
appComponent = DaggerAppComponent
.builder()
.apiModule(new ApiModule())
.greenDaoModule(new GreenDaoModule(this))
.build();
}
public AppComponent getAppComponent(){
return appComponent;
}
我们现在可以利用get方法获取创建的component,然后调用inject()方法将BasePresenter作为参数传进去,这样就完成了绑定BasePresenter依赖。
创建BasePresenter
BasePresenter的构造函数1
2
3public BasePresenter(BaseApp baseApp){
baseApp.getAppComponent().inject(this);
}
BasePresenter中使用依赖1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16public class BasePresenter {
@Inject
DaoSession daoSession;
/**
* 自定义http请求任务
*/
@Inject
public HttpTask httpTask;
public BasePresenter(BaseApp baseApp){
baseApp.getAppComponent().inject(this);
}
}
这样我们新建一个Presenter继承自BasePresenter,执行inject绑定,就直接可以使用Application提供的依赖来实例化对象了,而且这些实例都是singlton模式,生命周期等同于Application。
我们直接可以使用DaoSession来完成sql操作了。
继承Presenter
UserReguPresenter类继承自BasePresenter类,testLog()方法来测试数据库的操作
1 | public class UserReguPresenter extends BasePresenter{ |
参考文献
泡在网上的日子 详解Dagger2