dagger2从不懂到入门
dagger的目的是实现依赖注入
1、什么是依赖注入
举例:
不是依赖注入的例子:
class Person{
void playGame(){
Football football = new Football;
football.play();
}
}
是依赖注入的例子:
class Person{
void playGame(Football football){
football.play();
}
}
2、为什么需要dagger
其实你可以不需要它,你手动按照上述方式注入也是可以的。但如果你不想手动,而且想实现依赖注入而且不用写很多的代码就能正确的实现它,那你需要dagger。
3.我该如何使用dagger
首先你要对依赖注入这四个字有更深入的理解。
既然想通过依赖注入来完成你的开发,所以你应当知道它主要就是两点。
a.依赖从哪里来
b.我将如何注入(设置、传给)进去
通常的,依赖来自于new XXX(),而且注入的方式是构造函数(Person(String name))或直接设置(Person.name)。
所以dagger也不可避免的需要实现这两点,为了达到机器代替人工的目的,以及良好的拓展,
而作为开发者只需要 写接口 加注解 即可。
首先,dagger给我们提供了两种方式来实现依赖从哪里来,
1.在需要被注入的类的构造函数中加上@Inject注解
或2.实现一个Module类,在类上面加上@Module注解,并且,需要提供若干个返回需要被注入的类的方法,这些方法都要加上@Provider注解
举例说明:
public class Child{
@Inject
public Child(){
}
}
@Module
public class MyModule{
@Provider
public Parent providerParent(){
return new Parent();
}
}
然后,为了将这些需要被注入的类注入进入,需要做以下工作:
1.创建一个抽象类或接口 注解为@Compoment,并且需要在注解的参数里加上能够提供需要注入的Module类的名称。
2.对需要注入的类A的构造函数或成员加上@Inject注解,注意如果是在成员上加的,需要注意在Compoment接口或抽象类中添加一个方法,这个方法的参数只有一个,就是A。
举例说明:
@Compoment(module={MyModule.class})
public interface MyComponent{
}
public class Family{
@Inject Child child;
@Inject
public Family(Parent parent)
}
最后,在编译期,dagger会为我们生成多个类,其中有一个针对Component类的实现DaggerCompoment,
我们需要在恰当的时候(应是趁早)使用它,
使用方式大概是DaggerComponent.builder().xxxx.build();如果里面有方法可能还需要加上injectxxx()。
举例说明:
为了实现child 注入到Family我们需要在MyComponent补充一个方法:
@Compoment(module={MyModule.class})
public interface MyComponent{
public void injectToFamily(Family family);
}
然后编译完成后,会自动生成DaggerMyComponent实现类
然后在想使用Family之前,切记需要调用
DaggerMyComonent.builder().build().injectToFamily(???)
困难出现了,我们没有办法直接创建Family的实例,因为我们想通过dagger获取,
为了获取到Family实例,需要在MyCompoment再添加一个方法
@Compoment(module={MyModule.class})
public interface MyComponent{
public void injectToFamily(Family family);
public Family getFamily();
}
这样的话
MyComponent compoment = DaggerMyComonent.builder().myModule(new MyModule())build();
family = compoment.getFamily();
compoment.injectToFamily(family);
尘埃落定。
4.为什么这样可以实现依赖注入
dagger的做法是统一规范,创建与注入隔离;
首先在dagger中,一切被注入的对象的获取都是从Provicer<T> 接口的get方法中来.
为了实现这种统一的效果,dagger给每个这种对象的获取都建立了单独的工厂类,
通过@Inejct构造器来提供对象的---->Person_Facatory
看一下它是如何实现的:
public final class Person_Factory implements Factory<Person> {
private static final Person_Factory INSTANCE = new Person_Factory();
@Override
public Person get() {
return new Person();
}
public static Factory<Person> create() {
return INSTANCE;
}
/** Proxies {@link Person#Person()}. */
public static Person newPerson() {
return new Person();
}
}
注意 :
public interface Factory<T> extends Provider<T> {
}
在需要的地方调用
Person_Factory.create().get()即可
如果对象获取来自于Module,
dagger为每个在Module里的方法都增加了工程类
譬如 MyModule_getPersonFactory,两者套路差不多.
然后注入的过程发生在被注入对象的实例获取时(大部分);
如
MyComponent compoment = DaggerMyComonent.builder().myModule(new MyModule())build();
family = compoment.getFamily();//在getFamily调用的时候所依赖额对象也在完成创建。
而实现的思路也是先获取到创建Family的工厂,然后调用它的get方法.