Dagger系列:
- Dagger 2从浅到深(一)
- Dagger 2从浅到深(二)
- Dagger 2从浅到深(三)
- Dagger 2从浅到深(四)
- Dagger 2从浅到深(五)
- Dagger 2从浅到深(六)
- Dagger 2从浅到深(七)
- Dagger 2应用于Android的完美扩展库-dagger.android
Demo地址:
概述
在Dagger 2官方文档中,有这么一句话“A fast dependency injector for Android and Java.”,翻译过来的意思就是:适用于Android和Java的快速依赖注入。
这里主要是了解Dagger 2,对依赖注入不多叙述。不理解依赖注入的,可以参考以下博客:
Gradle配置
对于Gradle插件在2.3以上可以这么配置
dependencies {
compile 'com.google.dagger:dagger:2.x'
annotationProcessor 'com.google.dagger:dagger-compiler:2.x'
}
如果Gradle插件在2.3以下,就不得不借用apt插件了:
在根gradle中
dependencies { ... // 其他classpath classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' //添加apt命令 }
在App.gradle中
dependencies { compile 'com.google.dagger:dagger:2.x' apt 'com.google.dagger:dagger-compiler:2.x' }
@Inject
在Dagger 2中,使用javax.inject.Inject注解来标识需要依赖注入的构造函数和字段,以满足Dagger构造应用应用程序类的实例并满足其依赖性。
@Inject有两项职责:
- 注解构造函数:通过标记构造函数,告诉Dagger 2可以创建该类的实例(Dagger2通过Inject标记可以在需要这个类实例的时候来找到这个构造函数并把相关实例new出来)从而提供依赖关系。
- 注解依赖变量:通过标记依赖变量,Dagger2提供依赖关系,注入变量
注解构造函数
这里我们声明了,StudentBean对象,其构造函数被@Inject注解,以便被Dagger 2创建其实例。
public class StudentBean {
private int no;
private String name;
@Inject
public StudentBean() {
this.no = 1;
this.name = "赵四";
}
***
}
测试:
public class StudentActivity extends BaseActivity {
***
@Inject
StudentBean studentBean;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ButterKnife.bind(this);
// Log("student:StudentBean{no=1, name='赵四'}")
Log.d("test", "student:" + studentBean.toString());
tvStu.setText(studentBean.toString());
}
***
}
这里简单的注入了一个StudentBean实例,就算完成了。
注解字段
这时,就有一个疑问了,并不是所有的成员变量是基本数据类型,有的成员变量本身就是一个类的实例,这样我们是否还能使用依赖注入呢?既然有这样的疑问,不妨试一下。
创建AreaBean和ScoreBean,其构造函数均被
public class AreaBean { private String provice; private String city; @Inject public AreaBean() { this.provice = "四川"; this.city = "成都"; } *** } public class ScoreBean { private double chinese; private double math; @Inject public ScoreBean() { this.chinese = 90.5; this.math = 78.0; } *** }
修改Student实例,增加两个成员变量,分布是AreaBean、ScoreBean
public class StudentBean { private int no; private String name; @Inject AreaBean areaBean; @Inject ScoreBean scoreBean; @Inject public StudentBean() { this.no = 1; this.name = "赵四"; } *** }
测试
public class StudentActivity extends BaseActivity {
*** @Inject StudentBean studentBean; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ButterKnife.bind(this); // Log:student:StudentBean{no=1, name='赵四', areaBean=AreaBean{provice='四川', city='成都'},scoreBean=ScoreBean{chinese=90.5, math=78.0}} Log.d("test", "student:" + studentBean.toString()); tvStu.setText(studentBean.toString()); } ***
}
从测试结果,可以清晰的看到,即使@Inject注解字段,Dagger依然可以创建相应的实例并注入。
注意:
- 如果在类中有@Inject注解的字段,但是该字段的没有使用@Inject注解其构造函数。此时,Dagger将在请求时注入这些字段,但不会创建新实例,也就意味着将获得一个空的对象。使用@Inject注释添加一个无参数的构造函数,以指示Dagger也可以创建实例。此时,甚至会出现编译不成功,提示添加Provider方法(后续提到),提供所需实例。
- Dagger支持方法注入,不过,通常用来构造器或字段的依赖注入。
@Inject不是万能的
@Inject并不是万能,对于未知的事物,还是无能为力的。比如,所熟悉的接口,接口并不能创建实例,这时,我们就不能使用@Inject注解。
- 接口不能够创建
- 第三方库的类不能够创建
- 配置对象必须配置!
结束语
到这里,Dagger 2入门的简单例子已经实现了。简单总结一下:
- @Inject注解构造函数,表示该类委托Dagger创建实例
- @Inject声明属性变量,表示注入这个依赖。如果这个变量本事是一个实例对象,其构造函数必须使用@Inject注解,或者是通过Provider方法提供。
- @Inject并不是万能的。