dagger2 在 Android 中的使用

前言

dagger2 确实比较难上手,而我在写笔记之前也没完全整明白,只能记录些简单的应用


正文

一、dagger2 是什么?

dagger2 是依赖注入(Dependency Injection 简称 DI )框架中的一种,在编译期间自动生成代码,负责依赖对象的创建,貌似是目前最好的 DI 框架了。

二、为什么要用这玩意

1. 增加开发效率,省去重复代码

它可以把 new 对象的重复性工作做了,也能省去写单例方法的时间,也不用考虑单例模式的线程是否安全,因为这些都是 dagger2 的工作。

2. 进一步解耦
  • 先说“解耦”的概念:解耦是为了让类与类、模块与模块之间的相互影响的关系降到最低,并不是说完全没有关系。

  • 如果我们是通过 new 来创建对象的,那么当被 new 的对象所在的类的构造方法发生改变时,那么该类涉及到的类都要去修改,而 使用 dagger2 就不存在这方面的问题了。

3.方便测试

三、如何使用

1. 添加插件和依赖
  • 在工程目录下的 bulid.gradle 中添加 apt 插件
1
2
3
4
5
dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
  • 在 项目目录下的 bulid.gradle 中添加依赖
1
2
3
4
//版本最好匹配
apt 'com.google.dagger:dagger-compiler:2.2'
compile 'com.google.dagger:dagger:2.2'
provided 'org.glassfish:javax.annotation:10.0-b28'
2. 简单使用

现在有这么一个场景:

  • 一个类为:
1
2
3
4
5
6
7
8
9
10
11
12
//注意:构造方法没有参数
public class Hello {
public Hello(){
}
public String getSmg(){
return "Hello,World!";
}
}
  • 另一个类为:
1
2
3
4
5
6
7
8
9
10
public class MainActivity extends AppCompatActivity {
Hello hello;//我们要这个 hello 的对象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
  • 那么,在 MainActivity 中要 Hello 类的对象,我们该怎么做?(除了 new )

第一步 :我们要在 Hello 类中用 @Inject 标注构造函数

1
2
3
4
@Inject
public Hello(){
}

第二步:在 MainActivity 中也添加 @Inject

1
2
3
@Inject
Hello hello;
//注意,不能用 private 修饰

第三步:需要一个 Component 作为连接

1
2
3
4
5
6
7
8
//HelloComponent 可以是接口或者抽象类
@Component()
public interface HelloComponent {
//方法是固定写法,参数是因为要注入到 MainActivity 中
void inject(MainActivity activity);
}

第四步:还需要在 MainActivity 中做一些初始化操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class MainActivity extends AppCompatActivity {
@Inject
Hello hello;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化操作,注意被注入的 Hello 的构造方法是没有参数的
HelloComponent component = DaggerHelloComponent.builder()
.build();
component.inject(this);
}

第五步:这样就把 Hello 对象 注入到 MainActivity 中了,可以验证一下

3. 如果被注入的类的构造方法有参数呢,那就要引入 Module

Module 其中一个作用是为 构造方法提供参数用的,

  • 我现在把 Hello 类的构造方法加上参数
1
2
3
4
5
6
7
8
9
10
11
12
public class Hello {
@Inject
public Hello(String msg){
}
public String getSmg(){
return "Hello,World!";
}
}
  • 跟没有参数的构造方法相比,还要多加一步
1
2
3
4
5
6
7
8
9
10
11
// 创建一个 XXXModule 要用 @Module 标注
@Module
public class HelloModule {
//创建一个 providesXXX 方法,要用 @Provides 标注,返回值类型就是 Hello 构造方法的参数类型
@Provides
public String providesReturnMessage(){
return "Hello,World!";
}
}
  • 同时, HelloComponent 也要做修改
1
2
3
4
5
6
7
8
9
// @Component 后边加的东西,modules = 是固定写法 , HelloModule.class 表示需要注入的类
@Component( modules = HelloModule.class)
public interface HelloComponent {
void inject(MainActivity activity);
}
  • 另外 MainActivity 也要修改
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class MainActivity extends AppCompatActivity {
@Inject
Hello hello;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
HelloComponent component = DaggerHelloComponent.builder()
//跟之前的相比,多了 .helloModule(new HelloModule())
//这样一来,就串在一起了
.helloModule(new HelloModule())
.build();
component.inject(this);
}
  • 运行之后,也是对的

当然 dagger2 还有很多其他的注解和用法,以上是最简单的 Demo ,本人也没有在项目中实践过,无法提供更多的用法!