Dagger2 注入框架
http://www.cniao5.com/course/10127
https://github.com/luxiaoming/dagger2Demo
Dagger 同样使用注解来实现依赖注入,但它利用APT(Annotation Process Tool)在编译时生成辅助类,这些类继承特定父类或实现特定接口,程序在运行时 Dagger 加载这些辅助类,调用相应接口完成依赖生成和注入。Dagger 对于程序的性能影响非常小,因此更加适用于 Android 应用的开发。
依赖注入:像这种非自己主动初始化依赖,而通过外部来传入依赖的方式,我们就称为依赖注入
https://github.com/android-cn/blog/tree/master/java/dependency-injection
1.2 依赖注入相关概念
依赖(Dependency):如果在 Class A 中,有个属性是 Class B 的实例,则称 Class B 是 Class A 的依赖,本文中我们将 Class A 称为宿主(Host),并且全文用 Host 表示;Class B 称为依赖(Dependency),并且全文用 Dependency 表示。一个 Host 可能是另外一个类的 Dependency。
宿主(Host):如果 Class B 是 Class A 的 Dependency,则称 Class A 是 Class B 的宿主(Host)。
依赖注入:如果 Class B 是 Class A 的 Dependency,B 的赋值不是写死在了类或构造函数中,而是通过构造函数或其他函数的参数传入,这种赋值方式我们称之为依赖注入。
1.3 Dagger 基本使用
需要注意的是,如果构造函数含有参数,Dagger 会在调用构造对象的时候先去获取这些参数(不然谁来传参?),所以你要保证它的参数也提供可被 Dagger 调用到的生成函数。Dagger 可调用的对象生成方式有两种:一种是用@Inject 修饰的构造函数,上面就是这种方式。另外一种是用@Provides 修饰的函数,下面会讲到。
1.在 Boss 类的构造函数前添加一个 @Inject 注解,Dagger 就会在需要获取 Boss 对象时,调用这个被标记的构造函数,从而生成一个 Boss 对象。通过 @Inject 注解了构造函数之后,在 Activity 中的Boss 属性声明之前也添加 @Inject 注解。像这种在属性前添加的 @Inject 注解的目的是告诉 Dagger 哪些属性需要被注入。
2.具体怎么注入即设置的过程后面会详细介绍,这里简单透露下,APT 会在 MainActivity 所在 package 下生成一个辅助类 MainActivity$$InjectAdapter,这个类有个 injectMembers() 函数,代码类似:
public voidinjectMembers(MainActivity paramMainActivity) {paramMainActivity.boss= ((Boss)boss.get());
……
}
boss.get() 会调用 Boss 的生成函数。@Module 注解表示这个类是一个Module,Module 的作用是提供信息,让 ObjectGraph 知道哪些类对象需要被依赖注入,以及该怎么生成某些依赖(这在下面会具体介绍)。例如,上面这段代码中声明了需要依赖注入的类为 MainActivity。
2). @Inject 和 @Provide 两种依赖生成方式区别
a. @Inject 用于注入可实例化的类,@Provides 可用于注入所有类
b. @Inject 可用于修饰属性和构造函数,可用于任何非 Module 类,@Provides 只可用于用于修饰非构造函数,并且该函数必须在某个Module内部
c. @Inject 修饰的函数只能是构造函数,@Provides 修饰的函数必须以 provide 开头
Qualifier(限定符)
(1). 创建一个 @Qualifier 注解,用于区分两类程序员:
@Qualifier
@Documented
@Retention(RUNTIME)
public @interface Level {
String value() default "";
}
@Named和@Qulifier注解的使用
@Singleton
@Component 店长,关联需求方,提供方,
依赖注入组件Component,负责将对象注入到依赖需求方,它在实际编码中是一个接口,编译时Dagger2会自动为它生成一个实现类.
Dagger2的主要工作流程分为以下几步:
@Component(modules=MainModule.class)publicinterfaceMainComponent{voidinject(MainActivity mainActivity);
}
@Scope
注意注意注意:单例是在同一个Component实例提供依赖的前提下才有效的,不同的Component实例只能通过Component依赖才能实现单例.也就是说,你虽然在两个Component接口上都添加了PerActivity注解,但是这两个Component提供依赖时是没有联系的,他们只能在各自的范围内实现单例.(下一个例子会体现到)
组件依赖dependencies的使用
2.2 DAG(有向无环图)
Dagger 是支持传递依赖的。例如在上图中,当需要获取一个 CustomView,会首先获取一个 DataHelper 作为获取 CustomView 的必要参数;此时如果 DataHelper 还未初始化,则还要分别拿到 HttpHelper 和 Database 用来初始化 DataHelper;以此类推。
http://www.jianshu.com/p/1d84ba23f4d2
一般的IOC框架都是通过反射来实现的,但Dagger2作为Android端的IOC框架,为了不影响性能,它是通过apt动态生成代码来实现的.
Dagger2主要分为三个模块:
依赖提供方Module,负责提供依赖中所需要的对象,实际编码中类似于工厂类
依赖需求方实例,它声明依赖对象,它在实际编码中对应业务类,例如Activity,当你在Activity中需要某个对象时,你只要在其中声明就行,声明的方法在下面会讲到.
依赖注入组件Component,负责将对象注入到依赖需求方,它在实际编码中是一个接口,编译时Dagger2会自动为它生成一个实现类.
Dagger2的主要工作流程分为以下几步:
将依赖需求方实例传入给Component实现类
Component实现类根据依赖需求方实例中依赖声明,来确定该实例需要依赖哪些对象
确定依赖对象后,Component会在与自己关联的Module类中查找有没有提供这些依赖对象的方法,有的话就将Module类中提供的对象设置到依赖需求方实例中
通俗上来讲就好比你现在需要一件衣服,自己做太麻烦了,你就去商店买,你跟商店老板说明你想要购买的类型后,商店老板就会在自己的衣服供应商中查找有没有你所说的类型,有就将它卖给你.其中你就对应上面所说的依赖需求方实例,你只要说明你需要什么,商店老板则对应Component实现类,负责满足别人的需求,而衣服供应商则对应Module类,他负责生产衣服.也许这里有点绕,但经过下面的Demo,也许能够帮助你理解.