Dagger2的使用与理解(1)
来源:互联网 发布:简单优化模板源码下载 编辑:程序博客网 时间:2024/06/09 21:56
本篇是我写博客的第一篇,基于自己表达能力太差于是就想通过写博客来提高自己,表达可能会相当乱,自己本身水平一般般,如果有啥错误欢迎大家指出,如果能帮到大家那就是我最大的收获。
最近写项目的时候听学长的建议用了下Dagger2这个框架,发现这个框架特别好用,感觉整个项目的逼格就上去了。不过Dagger2在使用上还是有一点难度,当然可能对我这种新手而言,大神分分钟拿来使用。Dagger2也是谷歌官方推荐使用的框架。那么Dagger2是什么:
dagger2是一个基于JSR-330标准的依赖注入框架,在编译期间自动生成代码,负责依赖对象的创建。这句话看起来很官方,没错这是我在其他博客复制粘贴的。简单说就是通过这个框架,你不在用new来创建对象,而是写个注解@Inject就初始化好对象了。所谓的依赖就是:
A a = new A(B b);
我们就可以说b是a的依赖,因为预要创建a,需先创建b。我们想一下平时在Activity上是不是有很多成员变量,这些成员变量都是Activity的依赖,通常我们写一个Init()函数专用来初始化成员变量,如果这些成员变量又依赖于其他变量如像A这种,那我们还得先实例化B类对象。
public class DaggerActivity extends AppCompatActivity { A a1; A a2; A a3; A a4; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); } private void init() { B b1 = new B(); a1 = new A(b1); B b2 = new B(); a1 = new A(b2); B b3 = new B(); a1 = new A(b3); B b4 = new B(); a1 = new A(b4); }}
这就尴尬了一下好多行代码,看着极不舒服。如果使用Dagger2则变成这样子:
public class DaggerActivity extends AppCompatActivity { @Inject A a1; @Inject A a2; @Inject A a3; @Inject A a4; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DaggerActivityComponent.create().inject(this); }}
搞定。。。是不是很简洁明了
那么首先介绍下Dagger2最重要的几个注解
@Component:用这个注解修饰的叫做注入器,这个注解只能修饰接口和抽象类,通过注入器结合@Inject注解就能完成依赖的注入。如上代码:
@InjectA a1;DaggerActivityComponent.create().inject(this);
DaggerActivityComponent这个就是注入器的实现类,通过inject()方法,参数是Activity,为自己的依赖实现注入。注入哪些依赖用@Inject标识,这样就成功地将a1注入。所以@Inject的作用是
- 标记哪些依赖是我们要注入的
- 标记哪些要生成哪些依赖
第二点可以请看A和B类的代码
A类代码
public class A { private String name; private int id; @Inject public A(B b) { } //...省略get,set方法}
B类代码
public class B { private String name; private int id; @Inject public B() { } //...省略get,set方法}
A的构造器和B的构造器用@Inject标记,说明可以生成A类的依赖和B类的依赖。这里发现生成A类的对象依赖于B类对象,很明显注入器在注入A类对象的时候,肯定会先生成B类依赖,然后再注入。
看到这里可能大家有个疑问了,DaggerActivityComponent这个东西是怎么生成的,以及他是怎么实现依赖的注入的。我之前说@Component只能修饰接口和抽象类,下面是我写的接口:
@Componentpublic interface ActivityComponent { void inject(DaggerActivity daggerActivity);}
那么DaggerActivityComponent肯定和这个接口有关,实际上DaggerActivityComponent是利用APT注解处理工具动态生成的代码,你会发现你在module添加dependencies会添加一个东西:
apt 'com.google.dagger:dagger-compiler:2.0'
那么DaggerActivityComponent这个类在哪呢,如下图:切换到Project模式
DaggerActivityComponent 代码如下:
@Generated("dagger.internal.codegen.ComponentProcessor")public final class DaggerActivityComponent implements ActivityComponent { private Provider<A> aProvider; private MembersInjector<DaggerActivity> daggerActivityMembersInjector; private DaggerActivityComponent(Builder builder) { assert builder != null; initialize(builder); } public static Builder builder() { return new Builder(); } public static ActivityComponent create() { return builder().build(); } private void initialize(final Builder builder) { this.aProvider = A_Factory.create(B_Factory.create()); this.daggerActivityMembersInjector = DaggerActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), aProvider); } @Override public void inject(DaggerActivity daggerActivity) { daggerActivityMembersInjector.injectMembers(daggerActivity); } public static final class Builder { private Builder() { } public ActivityComponent build() { return new DaggerActivityComponent(this); } }}
DaggerActivityComponent类有Provider的成员变量,它是个接口,内容提供者,可以通过get()方法获取A的实例对象。
public interface Provider<T> { T get();}
DaggerActivityComponent还有个MembersInjector类,这个是成员注入器,也是个接口,上面调用DaggerActivityComponent.inject()方法实际上是调用MembersInjector的inject()方法。
public interface MembersInjector<T> { void injectMembers(T instance);}
我们知道依赖的注入是通过DaggerActivityComponent.create().inject(this)开始的,我们来看一下他的流程:
- DaggerActivityComponent里有个Builder对象,可见他是通过建造者模式去构建对象,先create()生成一个Builder,在调用Builder.builder(),最后还是调用了
private DaggerActivityComponent(Builder builder) { assert builder != null; initialize(builder); }
为什么要绕这么一圈呢 心好累,然后调用initialize()
private void initialize(final Builder builder) { this.aProvider = A_Factory.create(B_Factory.create()); this.daggerActivityMembersInjector = DaggerActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), aProvider); }
在这个方法中,初始化成员注入器和内容提供者,A_Factory是Factory接口的实现,Factory又继承Provider - - 什么方法都没有,你又在逗我
public interface Factory<T> extends Provider<T> {}public final class A_Factory implements Factory<A> { private final Provider<B> bProvider; public A_Factory(Provider<B> bProvider) { assert bProvider != null; this.bProvider = bProvider; } @Override public A get() { return new A(bProvider.get()); } public static Factory<A> create(Provider<B> bProvider) { return new A_Factory(bProvider); }}
调用A_Factory.create()方法完成对A_Factory的创建,注意这里传入了B_Factory,因为B是A的依赖,创建A时候需要用到B,所以A_Factory含有一个B_Factory的成员变量,同时重写Provider的get()方法,return new A(bProvider.get()), B_Factory与此类似只是直接返回B的实例。
因为每一次都返回new 出来的对象,所以一个类中的注入相同的依赖,每个依赖都是新的对象,而不是同一个对象,当然dagger2可以实现单例,这个在下面再说。
然后是成员注入器的生成,第一参数是MembersInjectors.noOp()的返回值,它是一个空实现的MembersInjector,表示注入已经到达父类的最顶端,第二个参数是A类的内容提供者。
this.daggerActivityMembersInjector = DaggerActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), aProvider);@SuppressWarnings("unchecked") public static <T> MembersInjector<T> noOp() { return (MembersInjector<T>) NoOpMembersInjector.INSTANCE; } private static enum NoOpMembersInjector implements MembersInjector<Object> { INSTANCE; @Override public void injectMembers(Object instance) { if (instance == null) { throw new NullPointerException(); } } }
最后调用inject(DaggerActivity daggerActivity)方法,实质上是调用daggerActivityMembersInjector.injectMembers(daggerActivity),
它首先判断一下空,然后调用父类的注入器为父类注入依赖,因为这边父类没有@inject标识的依赖,所以父类注入器supertypeInjector就是我们之前传入的空实现的MembersInjectors.noOp()的返回值。然后为DaggerActivity 的成员变量A注入依赖,因为这边是直接通过对象引用a,所以成员变量不能用private修饰。这样就为DaggerActivity的成员变量依赖注入好实例。
//a1AndA2AndA3AndA4Provider是上面传入的Provider<A> public void injectMembers(DaggerActivity instance) { if (instance == null) { throw new NullPointerException("Cannot inject members into a null reference"); } supertypeInjector.injectMembers(instance); instance.a1 = a1AndA2AndA3AndA4Provider.get(); instance.a2 = a1AndA2AndA3AndA4Provider.get(); instance.a3 = a1AndA2AndA3AndA4Provider.get(); instance.a4 = a1AndA2AndA3AndA4Provider.get(); }
@Inject还可以修饰在方法上面,为方法里的参数注入依赖
@Inject public void setA(A a){ //a 已经注入依赖 可以对a进行操作 }
对应的实际注入代码
instance.setA(a1AndA2AndA3AndA4AndAProvider.get());
如果我们要注入依赖的类的父类有@Inject标识,比如我们通常会让Activity继承一个BaseActivity,我们在BaseActivity里注入一个B类对象,那么上面注入器的构建就会传入父类的一个注入器,注入时,先注入父类的依赖,再注入子类的依赖。
//DaggerActivityComponent里多了个BaseActivity_MembersInjector成员变量,并在initialize初始化,传入DaggerActivity_MembersInjector。private void initialize(final Builder builder) { this.baseActivityMembersInjector = BaseActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), B_Factory.create()); this.aProvider = A_Factory.create(B_Factory.create()); this.daggerActivityMembersInjector = DaggerActivity_MembersInjector.create(baseActivityMembersInjector, aProvider); }//注入时,先调用supertypeInjector.injectMembers(instance),supertypeInjector就是传入的BaseActivity_MembersInjector@Override public void injectMembers(DaggerActivity instance) { if (instance == null) { throw new NullPointerException("Cannot inject members into a null reference"); } supertypeInjector.injectMembers(instance); instance.a1 = a1AndA2AndA3AndA4AndAProvider.get(); instance.a2 = a1AndA2AndA3AndA4AndAProvider.get(); instance.a3 = a1AndA2AndA3AndA4AndAProvider.get(); instance.a4 = a1AndA2AndA3AndA4AndAProvider.get(); instance.setA(a1AndA2AndA3AndA4AndAProvider.get()); }
通常我们要注入的依赖里还有要注入的依赖,比如A类里面有个B类的成员变量
public class A { private String name; private int id; @Inject B b1; @Inject public A(B b) { } //...省略get,set方法}
这时候DaggerActivityComponent又多了A_MembersInjector,构造传入B_Factory.create(),这个注入器就是用来为A注入B类的依赖。
private void initialize(final Builder builder) { this.baseActivityMembersInjector = BaseActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), B_Factory.create()); this.aMembersInjector = A_MembersInjector.create(B_Factory.create()); this.aProvider = A_Factory.create(aMembersInjector, B_Factory.create()); this.daggerActivityMembersInjector = DaggerActivity_MembersInjector.create(baseActivityMembersInjector, aProvider); }
A类注入器传入A的Provider对象里,在A的get()方法里我们还是先生成A类对象,再调用注入器注入,注意 :membersInjector就是我们上面传入的A类注入器,调用injectMembers()方法,为B类依赖注入对象。
@Override public A get() { A instance = new A(bProvider.get()); membersInjector.injectMembers(instance); return instance; } @Override public void injectMembers(A instance) { if (instance == null) { throw new NullPointerException("Cannot inject members into a null reference"); } instance.b1 = b1Provider.get(); }
注意:不能循环注入:在A类里面在注入一个A类依赖,这个将会导致一直注入下去,编译会出错。
//不能循环注入// @Inject// A a1;
最后简单的总结一下,只要有@Inject标识,就会对应生成相应的MembersInjector,如果要注入的类有父类要注入,先注入父类,在注入子类,最后注意不能循环注入。
- -讲的很罗嗦,大家看看就好,下面几篇依次说下另外几个注解:@Scope,@Module, @Provides, @SubComponent, @Qualifier和@Named。
- Dagger2的使用与理解(1)
- Dagger2的使用与理解(2)
- Dagger2的使用与理解(3)
- Dagger2的使用与理解(4)
- Dagger2的使用(1)
- Dagger2的了解与使用
- Dagger2 学习与理解
- Dagger2自己的理解
- android框架学习篇-Dagger2的理解与应用
- 一些关于dagger2的理解
- 我所理解的Dagger2
- 我所理解的Dagger2
- dagger2框架的学习理解
- 我对Dagger2的理解
- Dagger2的使用
- 对Dagger2的使用
- Dagger2的使用
- Dagger2的简单使用
- 前端MVC
- 关于Map集合的三种遍历方法
- 针对Excel表格文件操作的编程实现
- jdbc——事务
- 基于RNN的文本生成算法的代码运转
- Dagger2的使用与理解(1)
- MyBatis3入门程序(02_注册别名typeAlias)
- AOJ 0005 GCD and LCM
- Redis主从配置详细过程
- jdbc——程序优化
- Jmeter+jenkins接口性能测试平台实践整理(一)
- ajax轮询 学习心得
- MyBatis3入门程序(03_使用Mapper接口方式)
- AsyncTask加载图片。