一、前言
Dagger出来也不久时间了,据说也是较为难理解的框架之一。目前已经出来Dagger2了。最近在项目刚好准备重构mvp模式,但是mvp模式会带来大类的接口,而且也间接说明要大量实例化接口层对象。如果引用dagger模板化变成,无疑能够提高我们开发的效率。
熟悉spring框架的人肯定很熟悉aop编程,其实现在大量框架也引用了这种思想,例如rxjava、arouter等等。第一篇我先简单介绍Dagger2的具体用法(其实不难理解,有时间的读者可以尝试阅读编译生成的代码,看看他们是如何关联起来的),另一篇则介绍下Dagger2的android扩展库Dagger2-android与mvp模式如何结合起来。
二、Dagger2用法
(0) Dagger2引入指南
1.首先在你的library module引入(2.11版本举例)
compile 'com.google.dagger:dagger:2.11'
2.其次在你需要用的applicationo module引入compiler组件
annotationProcessor 'com.google.dagger:dagger-compiler:2.11'
(1)简单入手
1.创建一个带注入的实体
public class Demo {
@Inject
public Demo() {
// 构造方法默认注解,并且无参数...
}
public void action(){
Log.e("SIVEN","demo action");
}
}
2.创建一个注入器,绑定对应的activity
@Component
public interface MainActivityComponent {
void inject(MainActivity mainActivity);
}
3、在对应的activit引入注解器并注解Demo类
@Inject
Demo demo;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
DaggerMainActivityComponent.create().inject(this);
super.onCreate(savedInstanceState);
//...
demo.action(); // 执行注入对象方法
}
或者
1.创建一个实体
public class Demo {
public Demo() {
// 构造方法默认注解,并且无参数...
}
public void action(){
Log.e("SIVEN","demo action");
}
}
2.创建一个注入器,绑定对应的activity
@Component
public interface MainActivityComponent {
void inject(MainActivity mainActivity);
}
3.创建一个module工厂,并且绑定指定注入器
@Module(components = MainActivityComponent.class)
public abstract class MainActivityModule {
@Provides
Demo provideDemo(){
return new Demo();
}
}
4、验证
@Inject
Demo demo;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
DaggerMainActivityComponent.create().inject(this);
super.onCreate(savedInstanceState);
//...
demo.action(); // 执行注入对象方法
}
(2)既爱又恨的component与module
首先解释下这两个专属名词代表什么意思。
- component
可以理解成注解器,即将注解对象与注解目标关联起来的作用。注解对象例如我要在activity使用注解、或者在fragment使用注解;注解目标即我在activity或fragment中要注解那个实例,例如案例的Test实体。标准写法如下:
@Component
public interface MainActivityComponent {
void inject(MainActivity mainActivity); // 注解对象,具体注解在哪个activity
}
- module
可以理解提供对象实例的工厂类,可有可无(待会解释)。module提供很多注解方式,例如Singleton(单例)、Scope(局部单例)等。其中module的标准写法为如下:
@Module(components = 目标注解器.class)
public abstract class MainActivityModule {
@Provides // 必须有provides操作符
Demo provideDemo(){ // 命名规则provide+目标类名
return new Demo();
}
}
(3)如何理解module可有可无?
首先我们看下什么时候是可以不用module的。在上面的案例中,我们定义了Demo这个model,并且在其构造方法中加上@Inject注解,如下:
@Inject
public Demo() {
// 构造方法默认注解,并且无参数...
}
其次不需要定义module,只要在注解对象(MainActivity)中关联注解器component,使用@Inject注解符号即可注解实例Demo对象,例如如下:
@Inject
Demo demo;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
DaggerMainActivityComponent.create().inject(this);
super.onCreate(savedInstanceState);
//...
demo.action(); // 执行注入对象方法
}
这里有没有人有什么疑问?为啥简单在构造器标记 @Inject就可以实现注解,为什么还要搞一个module这么复杂?的确,自己创建的类我们可以在构造方法里面申明。好了,第三方的类都封装在jar,那我们怎么去他的构造方法申明?所以,module就是为这个而存在的。
module,类似设计模式的类工程设计思想。通过创建module的时候申明component可以指定与哪个注解器相关联。所以在注解对象中,所有的注解实例都会通过module提供的provide工厂方法进行实例化。这也是module设计的巧妙之处。具体读者可以参考上面的案例。
四、总结
虽然以前有接触过spring,像aop这种设计思想进来终于向移动客户端靠齐了。尽管注解这种东西比较难理解与消化,真的要了解注解、预编译这种,非常强烈建议去阅读注解后预编译生成的文件究竟是这么关联操作的。笔者也是了解了三四天才差不多明白啊~
下一篇讲下Dagger2的扩展库Dagger-Android,基于android的扩展库,能很好配合mvp模式喔~