大家好,欢迎来到IT知识分享网。 为了介绍Dagger2的使用,我们搭建了一个Demo来逐步分析,大家可以在这里
下载源码(https://github.com/dushaofeng/DaggerDemo.git)。
上一节我们介绍了
《Dagger2教程一之配置(原)》,这一节我们来介绍Dagger2的具体使用方法。
一、原始方式
我们先来看一下如果不使用Dagger的情况,我们在Activity中创建一个Bean的对象,其构造方法无需传递任何参数,但是内部会初始化其成员name,然后在Activity中使用该对象。
Bean的内容为:
public class Bean {
private String mName = null;
public Bean() {
this.mName = "原始方式";
}
public String getName() {
return mName;
}
}
在Activity中创建并使用该对象:
private void testOrignal() {
Bean bean = new Bean();
Log.d(TAG, "不使用Dagger时 Name:" + bean.getName());
}
其结果如下图所示:
二、最简单的Dagger使用方式
接下来我们通过一个例子来介绍如何通过Dagger来实现上面的代码。
2.1、改造Bean
和Bean类似,我们新建一个BeanForDagger的对象,其内容为:
public class BeanForDagger {
private String mName = null;
@Inject
public BeanForDagger() {
this.mName = "Dagger方式";
}
public String getName() {
return mName;
}
}
这个BeanForDagger和Bean的区别有两点:
1、mName的初始化名称不同,这是为了区分两个对象
2、BeanForDagger的构造方法多了@Inject的注释,它会告诉Dagger用这个方法来注入目标类
2.2、创建Component文件
然后我们我们新建一个BeanComponent的接口(文件),其内容如下:
@Component
public interface BeanComponent {
void inject(MainActivity activity);
}
请注意,这个接口使用了@Component的注释。
2.3、使用Dagger
经过上面修改之后,我们就可以使用Dagger来自动创建BeanForDagger对象了。
首先在Activity中声明该变量:
@Inject
BeanForDagger mBeanForDagger;
然后我们可以这样使用该变量:
private void testDagger() {
// 触发Dagger机制
DaggerBeanComponent.create().inject(this);
if (mBeanForDagger != null) {
Log.d(TAG, "使用Dagger注入变量,mBeanForDagger Name:" + mBeanForDagger.getName());
}
}
运行之后的Log如下:
这说明我们已经可以使用mBeanForDagger了,但是请注意,在Activity中(以及BeanComponent或BeanForDagger中),我们并没有创建(new)BeanForDagger的对象。
也就是说,Dagger帮助我们完成了创建BeanForDagger对象的工作。
2.4、Dagger创建对象的过程
这一节我们通过最简单的描述来简单介绍一下Dagger是如何帮助我们创建BeanForDagger对象的。
首先,在Activity的testDagger方法中,多了这么一句:
DaggerBeanComponent.create().inject(this);
而这里的DaggerBeanComponent是Dagger根据BeanComponent自动生成的,
每一个XXXComponent都会生成对应的DaggerXXXComponent文件。
当调用inject()时,DaggerBeanComponent就会扫描inject方法中的参数(当前就是Activity)中
用@Inject标记的变量,对于当前的Activity来说,只有mBeanForDagger变量被标记。
找到这个需要被注入的变量后,发现他的类型是BeanForDagger,接下来,Dagger就会去搜索BeanForDagger的类,然后找到该类中
用@Inject标记的构造方法,并用该构造方法来创建对象。
这个过程简单来说就是这个步骤:
1、通过DaggerXXXComponent的Inject()触发注入过程
2、搜索目标类中用@Inject标识的需要注入的对象
3、找到需要注入对象后,寻找该对象中用@Inject标识的构造方法,完成自动创建过程
2.5、用到的注释
截至目前,我们用到了两个注释:
@Inject和@Component,其中的Inject用来注释需要注入的目标对象,以及用来注入的构造方法,而Component用来触发注入机制。
三、带参数的构造方法
上面的使用过程虽然简单,但是他的特点很明显:
需要被注入的对象的构造方法无需传参数!
因为无需传参,所以Dagger找到该构造方法后可以使用new BeanForDagger()的方法来完成创建工作。
那么疑问就来了,如果这个构造方法需要参数时,怎么办?Dagger是否具有创建参数的能力?
比如我们的BeanForDagger对象的构造方法是这样的:
@Inject
public BeanForDagger(ParamForDagger param) {
this.mName = param.mParamName;
}
那么Dagger如何才能获得ParamForDagger的参数呢?
解决的方法很简单,只需要
在ParamForDagger的构造方法中标记@Inject即可,如这样:
public class ParamForDagger {
String mParamName = null;
@Inject
public ParamForDagger() {
mParamName = "ParamName";
}
}
这样一来,当Dagger在创建BeanForDagger时发现其构造方法需要ParamForDagger的对象,那么Dagger就会
递归查找ParamForDagger类中使用Inject标记的构造方法,找到后,先创建ParamForDagger,然后再用他来创建BeanForDagger。
也就是说,
Dagger具备递归创建对象的能力。
这个例子执行结果就是,将BeanForDagger中的mName初始化为ParamForDagger中的值:ParamName,运行结果是这样的:
四、一个疑问
上面的例子虽然介绍了有参数和无参数的注入,但他们都有两个局限:
1、需要修改构造方法,添加@Inject的标识,但是对于一些jar包中的方法,或者第三方API中提供的方法,
我们无法修改其源码;
2、虽然构造方法中可以传递参数,但是实际上对这个参数也是有要求的,这个参数虽然会递归创建,
但递归的最后一层的构造方法中还是无法传参的;
要解决这两个问题,请继续看下一篇
《Dagger2教程三之构造方法带参数的情况(原)》
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/15937.html