引入dagger2

参考dagger2的GitHub说明.

1
2
3
4
dependencies {
compile 'com.google.dagger:dagger:2.x'
annotationProcessor 'com.google.dagger:dagger-compiler:2.x'
}


###几个常用的注解
@Module, @Component, @Inject, @Provides

生成对象的方式

生成对象有两个方式:
①.@Inject 注解提供方式:在所需类的构造函数中直接加上 @Inject 注解
②.@Module 注解提供方式:通过新建一个专门的提供这类来提供类实例,然后在类名上面添加 @Module 注解,在类中自己定义方法,手动通过 new 来进行创建,这种主要是针对第三方库中,我们无法直接在构造函数中添加 @Inject 注解的情况。

方式①

1> 用@Inject注解Bean类的构造方法

1
2
3
4
5
6
7
8
9
10
11
public class Apple {

@Inject
public Apple() {

}

public String getDescription() {
return "this is a red apple";
}
}

2>使用@Component注解自己的Component类.比如下面的AppleComponent, 该类用@Component注解, 类中提供inject方法(方法名可以随便写, 一般用inject), 方法的参数Main9Activity是需要使用注解生成Apple的类.

1
2
3
4
@Component
public interface AppleComponent {
void inject(Main9Activity main9Activity);
}

3>编译项目, Android Studio
Build–>Make Project
或者直接点击
Aaron Swartz

4>使用@Inject注解需要生成Apple的变量, 注入Main9Activity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Main9Activity extends AppCompatActivity {

@BindView(R.id.textView9)
TextView mTextView9;

@Inject
Apple mApple;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main9);
ButterKnife.bind(this);

DaggerAppleComponent.builder().build().inject(this);

mTextView9.setText(mApple.getDescription());
}
}

1
DaggerAppleComponent.builder().build().inject(this);

这里, 上面第4步生成了DaggerAppleComponent, 实现了接口AppleComponent的inject方法, 此时, 注入Main9Activity, 将Main9Activity和Apple关联起来.

那么, 思考一个问题, 如果这个Apple类我们并不能修改, 也就是我们不能再Apple的构造函数上添加注解@Inject(比如第三方库里的类), 那我们怎么处理呢? 这就得用我们第二种注解方法了.

方式②

1> 生成一个普通的Bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Cloth {
private String color;

public String getColor() {
return color;
}

public void setColor(String color) {
this.color = color;
}

@Override
public String toString() {
return color + "布料";
}
}

2>构建Module
注解@Module表明这是一个Module类, 方法上的@Provides表明该方法生成一个返回值为Cloth类型的依赖对象

1
2
3
4
5
6
7
8
9
10
@Module
public class MainModule {

@Provides
public Cloth getCloth() {
Cloth cloth = new Cloth();
cloth.setColor("红色");
return cloth;
}
}

3>书写Component

1
2
3
4
@Component(modules=MainModule.class)
public interface MainComponent {
void inject(MainActivity mainActivity);
}

MainComponent是一个接口, 接口上用@Component注解, 表明这是一个Component, @Component的参数model=MainModule.class, 将MainMoudle和MainComponent关联起来, MainComponent中有一个inject的方法(方法名随意, 方法参数是需要使用到注解生成对象的类, 这里是需要在MainActivity中使用注解生成Cloth)
4>AS: Build–>make Project
5>在MainActivity中使用注解.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Main3Activity extends AppCompatActivity {

private TextView mTextView;

@Inject
Cloth mCloth;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);

mTextView = (TextView) findViewById(R.id.textView2);

DaggerMainComponent.builder().mainModule(new MainModule()).build().inject(this);
}
}

Dagger2原理分析

1.就使用上面方式一的例子吧.注入的目的是在Main9Activity中生成Apple的实例.
我们从

1
DaggerAppleComponent.builder().build().inject(this);

开始分析吧.
首先, 看下DaggerAppleComponent的源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public final class DaggerAppleComponent implements AppleComponent {
private MembersInjector<Main9Activity> main9ActivityMembersInjector;

private DaggerAppleComponent(Builder builder) {
assert builder != null;
initialize(builder);
}

public static Builder builder() {
return new Builder();
}

public static AppleComponent create() {
return new Builder().build();
}

@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {

this.main9ActivityMembersInjector =
Main9Activity_MembersInjector.create(Apple_Factory.create());
}

@Override
public void inject(Main9Activity main9Activity) {
main9ActivityMembersInjector.injectMembers(main9Activity);
}

public static final class Builder {
private Builder() {}

public AppleComponent build() {
return new DaggerAppleComponent(this);
}
}
}

2.DaggerAppleComponent.builder(): builder()方法里new 了一个DaggerAppleComponent.Builder, 并返回这个新建的Builder.
3.DaggerAppleComponent.builder().build(): build()方法里new了DaggerAppleComponent的实例, 并将上个方法创建的Builder传给了DaggerAppleComponent的构造方法.
在DaggerAppleComponent的构造方法里, 调用了DaggerAppleComponent.initialize(builder).
在initialize里. 调用了Main9Activity_MembersInjector.create(Apple_Factory.create())方法.
4.现在我们来看一下这个Main9Activity_MembersInjector.create(Apple_Factory.create())方法都做了什么事情.
首先, 看下Apple_Factory的源码

1
2
3
4
5
6
7
8
9
10
11
12
public final class Apple_Factory implements Factory<Apple> {
private static final Apple_Factory INSTANCE = new Apple_Factory();

@Override
public Apple get() {
return new Apple();
}

public static Factory<Apple> create() {
return INSTANCE;
}
}

从源码可知, Apple_Factory是个单例, create方法返回了该单例. get方法返回了一个Apple实例.
这个时候就要注意了, 我们注解的目的是什么? 就是生成一个Apple实例啊, 那么, 现在我们知道, Apple_Factory的get方法创建了一个Apple实例. 记住这一点. 我们继续向下看Main9Activity_MembersInjector.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public final class Main9Activity_MembersInjector implements MembersInjector<Main9Activity> {
private final Provider<Apple> mAppleProvider;

public Main9Activity_MembersInjector(Provider<Apple> mAppleProvider) {
assert mAppleProvider != null;
this.mAppleProvider = mAppleProvider;
}

public static MembersInjector<Main9Activity> create(Provider<Apple> mAppleProvider) {
return new Main9Activity_MembersInjector(mAppleProvider);
}

@Override
public void injectMembers(Main9Activity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.mApple = mAppleProvider.get();
}

public static void injectMApple(Main9Activity instance, Provider<Apple> mAppleProvider) {
instance.mApple = mAppleProvider.get();
}
}

Main9Activity_MembersInjector.create(Apple_Factory.create())方法到底做了什么呢?
我们已知Apple_Factory.create()返回了单例Apple_Factory并且, Apple_Factory.get方法返回了Apple的实例.
现在来看Main9Activity_MembersInjector.create, 在该方法中, new了一个Main9Activity_MembersInjector, 并将Apple_Factory的单例传给这个构造方法.
在Main9Activity_MembersInjector的构造方法中, 将Apple_Factory的实例赋值给了Main9Activity_MembersInjector的成员变量mAppleProvider, 此时, 通过成员变量mAppleProvider的get方法就可以得到一个Apple的实例了.
5.DaggerMainComponent.builder().mainModule(new MainModule()).build().inject(this): 最后这个inject方法做了什么呢?

1
2
3
4
@Override
public void inject(Main9Activity main9Activity) {
main9ActivityMembersInjector.injectMembers(main9Activity);
}

1
2
3
4
5
6
7
@Override
public void injectMembers(Main9Activity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.mApple = mAppleProvider.get();
}

此时, 我们终于找到了这个给Main9Activity的成员变量mApple赋值的地方了, 通过inject调用Main9Activity_MembersInjector.injectMembers方法, 在injectMembers方法中, 通过单例Apple_Factory.get获取Apple的实例, 并将该实例直接赋值飞Main9Activity.mApple, 到此, 给mApple生成实例的过程就结束了. 当然, 这里分析的只是最简单的使用模式, 随着Dagger2的使用, 代码会越来越复杂.
在这里, 我们也可以明白, 为什么成员变量mApple不能是private或者protected的, 因为给mApple赋值的方式使用过instance.mApple来实现的, 如果mApple是private或者protected, 这里将会报错.