入门
要实现依赖注入,首先要声明一个依赖对象的需求,这个声明是通过@Inject注解来实现的,所以Car类的实现如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
public class Car {
String mName;
@Inject
Engine mEngine;
public Car(Engine engine){
mEngine = engine;
}
public String getName(){
return mName;
}
Engine getEngine(){
return mEngine;
}
}
|
声明了需求之后,需要声明提供方。提供方声明有两种方式:
- 使用
@Inject注解被依赖对象的构造方法;
- 使用
@Provide注解Module类的普通方法。
先用第一种来实现:
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
|
class Engine {
public final int CYLINDER_FUEL_COST = 10;
int mCylinderNumbers;
@Inject
public Engine(){
mCylinderNumbers = 1;
}
public Engine(int cylinderNumbers){
this.mCylinderNumbers = cylinderNumbers;
}
public int getCylinderNumbers(){
return mCylinderNumbers;
}
public void run(Fuel fuel){
fuel.burn(getCylinderNumbers() * CYLINDER_FUEL_COST);
}
}
|
这样就声明了一个完整的依赖关系,但是在Dagger2里,我们声明的依赖关系是无法直接使用的,我们需要使用声明组件(Component)作为依赖关系的容器,Dagger2才会根据组件里要求的依赖关系,帮我们生成对应的Dagger开头的工具类。我们使用@Component来声明一个组件。
1
2
3
4
|
@Component
public interface EngineComponent {
Engine getEngine();
}
|
这里有几个问题:
- 为什么组件是一个接口,而不是一个类?
- getEngine方法即不见调用方,也不见提供方,dagger如何绑定需求方和提供方?
这里我们先不做解答,我们先试试效果,构建一下生成DaggerEngineComponent类,并用它为Car类创建Engine对象。
1
2
3
4
5
6
7
8
|
public class Main {
public static void main(String[] args){
Engine engine = DaggerEngineComponent.builder().build().getEngine();
Car car = new Car(engine);
System.out.println("cylinderNumbers : " + car.getEngine().getCylinderNumbers());
}
}
|
运行一下看到打印:
1
2
|
cylinderNumbers : 1
Process finished with exit code 0
|
其实很容易误导我们,以为Dagger2对依赖关系的使用也进行了约束和实现,这是不利于我们清楚地认知dagger2的。在上面的例子中,如果把依赖声明放到Main中,也是可以正常工作的,有兴趣的同学可以自己试验一把。
使用Dagger2实现Engine的注入
注入类型也是依赖关系的一种,也需要Component作为它的容器,才能使用。我们创建一个CarComponent:
1
2
3
4
|
@Component
public interface CarComponent {
void inject(Car car);
}
|
这就声明了注入类型的使用了,Dagger2同样会根据容器的声明为我们生成Dagger2开头的组件。如果你想在EngineComponent里,通过这个方法来声明使用这个注入类型,也是可以的。
1
2
3
4
5
6
7
8
|
public class Main {
public static void main(String[] args){
Car car = new Car(null);
DaggerCarComponent.builder().build().inject(car);
System.out.println("cylinderNumbers : " + car.getEngine().getCylinderNumbers());
}
}
|
运行结果和上面的调用方式是一样的,这里就不贴了。发现没有,这里我们没有再通过组件创建Engine对象了,很神奇是不是?
是的,如果我们在组件中声明了注入或者需求类型,Dagger2会根据声明的类型自动查找这个类型依赖的所有的其他需求类型,并在注入组件中帮我们一一实现需求的创建(如果需求类型找不到,就会报编译错误),后面我们进行原理分析的时候再进行讲解,这里先记住这点。也正是因为这个自动实现的逻辑,让初学者在dagger2的工作原理的理解上颇费周章,希望这样讲解过后,读者可以理解需求类型和注入类型是相互独立的两个逻辑,是可以灵活使用的。