使用Dagger 2进行依赖注入

当我们写代码时总会遇见好多依赖关系,为了解决依赖达到代码之间的低耦合,通常我们会运用依赖注入技术。通常如下两种方式解决依赖:

静态依赖注入
动态依赖注入(java中通过注解方式实现)
本着what-how-why原则去进行分析问题、解决问题。

原理

依赖注入的原理网上有很多,大家可以看看,我找了两篇,感觉写不错。

martinfowler

codethink

dagger

在 Android 上比较流行的有 RoboGuice、Dagger 等。其中 Dagger 是我现在正在项目中使用的。

Dagger已经加入Google I/O, 是Square开发的依赖注入库, 发布2.0版本. Dagger表示有向非循环图(Directed Acyclic Graph, DAGger). 好处和优点有很多, 参考, 所有优秀的开源库, 本质上都是让程序更加清晰, 编写更加容易. 让我们来看看怎么使用?

dagger2主要包含inject, module, component三个部分, 即:
Inject, 依赖注入dependency injection, 把定义的类注入声明.
Module, 模块, 提供若干类, 在依赖注入中使用.
Component, 组件, 注册若干模块至项目中.

show me the code

我想现在有好多疑问,那就让我们行动起来看看怎么使用dagger

Configure

build.gradle 配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apply plugin: 'com.neenbedankt.android-apt'
//project gradle
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
}
}
//module gradle
android {
...
}
dependencies {
apt 'com.google.dagger:dagger-compiler:2.2'
compile 'com.google.dagger:dagger:2.2'
provided 'javax.annotation:jsr250-api:1.0'
...
}

Module

  • @Module: Modules类里面的方法专门提供依赖,所以我们定义一个类,用@Module注解,这样Dagger在构造类的实例的时候,就知道从哪里去找到需要的 依赖。modules的一个重要特征是它们设计为分区并组合在一起(比如说,在我们的app中可以有多个组成在一起的modules)。
  • @Provide: 在modules中,我们定义的方法是用这个注解,以此来告诉Dagger我们想要构造对象并提供这些依赖。
1
2
3
4
5
6
7
8
@Module
public class ActivityModule {
@Provides
UserInfo provideUserInfo() {
return new UserInfo();
}
}

UseInfo:

1
2
3
4
5
6
7
8
9
public class UserInfo {
public String name;
public String age;
public UserInfo() {
this.name = "jason";
this.age = "20";
}
}

Inject

@Inject: 通常在需要依赖的地方使用这个注解。换句话说,你用它告诉Dagger这个类或者字段需要依赖注入。这样,Dagger就会构造一个这个类的实例并满足他们的依赖。

Dagger给了我们一堆选择用来注入依赖:

  • 构造方法注入:在类的构造方法前面注释@Inject
  • 成员变量注入:在类的成员变量(非私有)前面注释@Inject
  • 函数方法注入:在函数前面注释@Inject
1
2
@Inject
UserInfo userInfo;

Component

@Component: Components从根本上来说就是一个注入器,也可以说是@Inject和@Module的桥梁,它的主要作用就是连接这两个部分。 Components可以提供所有定义了的类型的实例,比如:我们必须用@Component注解一个接口然后列出所有的@Modules组成该组件,如 果缺失了任何一块都会在编译的时候报错。所有的组件都可以通过它的modules知道依赖的范围。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Component(modules = ActivityModule.class)
public interface ActivityComponent {
void inject(MainActivity activity);
final class Initializer {
private Initializer() {
} // No instances.
public static ActivityComponent init() {
return DaggerActivityComponent.builder().activityModule(new ActivityModule()).build();
}
}
}

Invoke

1
2
3
4
5
6
7
8
9
10
11
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mActivityComponent = ActivityComponent.Initializer.init();
mActivityComponent.inject(this);
Log.d(TAG, userInfo.name + userInfo.age);
}

源码的GitHub 下载地址

参考

Tasting Dagger 2 on Android

JasonThink wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!