上一篇了解了Dagger是什么东西,以及使用它的优点。 接下来就来写个最简单的demo试试水。
先来看下在不使用Dagger的情况下, 在一个Activity中使用User bean类的方式,很简单如下所示:
User.java
/**
* Created by Danny on 17/8/30.
*/
public class User {
private String name;
private int age;
public User(String name) {
this.name = name;
}
public User(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
}
MainActivity.java
User user;
public void initData() {
textView = ((TextView) findViewById(R.id.tv1));
user = new User();
user.setName("Danny");
textView.setText("user is " + user.getName());
}
很简单,只要在MainActivity中声明一个全局变量User, 然后在initData方法中初始化User并设置name属性,然后将其设置到TextView控件上
接下来看一下如何使用Dagger将User进行依赖注入,并显示到TextView上
首先在Project的build.gradle中添加如下依赖
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.0'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
ext {
daggerVersion = '2.11'
}
之后在app的build.gradle中添加如下依赖
// dagger support
apt "com.google.dagger:dagger-compiler:$rootProject.daggerVersion"
provided 'org.glassfish:javax.annotation:10.0-b28'
compile "com.google.dagger:dagger:$rootProject.daggerVersion"
代码中首先将MainActivity中的user变量,添加@Inject注解,如下所示
@Inject
User user;
public void initData() {
textView = ((TextView) findViewById(R.id.tv1));
//使用Dagger,不再需要初始化User对象
//user = new User();
user.setName("Danny");
textView.setText("user is " + user.getName());
}
然后在User.java的构造器方法也添加@Inject注解,如下所示:
/**
* Created by Danny on 17/8/30.
*/
public class User {
private String name;
private int age;
@Inject
public User() {
Log.e("DANNY", "default construction called");
}
public User(String name) {
this.name = name;
}
public User(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
}
可以看到在User的空参构造器上添加了@Inject的注解。如果这个时候我们就运行程序会发现报空指针 user为null。 也就是说Dagger并没有成功创建对象并注入到MainActivity中。 这是因为我们少了一个最重要的东西 — Component(在Dagger中,一般叫注射器)。
创建如下类,并用@Component注解
@Singleton
public interface UserComponent {
void bind(MainActivity mainActivity);
}
然后在MainActivity的initData方法中添加如下代码:
public void initData() {
textView = ((TextView) findViewById(R.id.tv1));
//告诉MainActivity,其中@Inject注解的属性都由Dagger进行依赖注入
DaggerUserComponent.builder().build().bind(this);
//使用Dagger,不再需要初始化User对象
//user = new User();
user.setName("Danny");
textView.setText("user is " + user.getName());
}
这样就可以成功运行并显示User name到TextView上了
解释一下:
- 在UserComponent接口中添加bind(MainActivity)方法,这个方法的作用就是通知MainActivity,如果在MainActivity中有被@Inject注解的变量则会通过UserComponent这个接口去初始化,并注入MainActivity中
- 而UserComponent初始化变量的规则就是先找到MainActivity中被@Inject注解的变量(比如User),然后到User类中找到被@Inject注解的构造器,进行初始化new的操作
代码运行流程:以上代码是如何工作的呢?
- 首先定义一个类User 并在其构造函数用@Inject标注,表示告诉Dagger2这是我的构造函数,如果有地方要用到我,就用该构造函数对我实例化;
- 创建一个@Component标注的注入器接口,并在注入器中使用 void bind(MainActivity MainActivity);来表明哪里要用到注入器;这里表示MainActivity中要用到该注入器
- 在MainActivity中对需要注入的类 User用@Inject进行标注,表示该类需要被注入,即实例化;
- 在MainActivity中对注入器进行初始化DaggerActivityComponent.builder().build().inject(this); 初始化后该注入器就可以正常使用了;