依赖注入
为了理解dagger2在android中的应用,我们需要先理解为什么需要依赖注入。
为什么我们需要依赖注入
依赖注入是来源于控制反转的概念。在java中,我们经常需要在一个class中创建另外一个class的实例,但是这会引入耦合。这为重用这个class,以及测试带来困难。经常改动一个class,需要修改所有相关的class。
所以使用dagger的最大优势就是增加class的重用性,以及可测试性。
dagger1 与 dagger2区别
dagger1是利用反射在runtime进行依赖注入。这样做的不足有两点:
- reflection的效率比较低,速度慢。
- 在runtime进行依赖分析会增加crash的可能性。
dagger2利用的是注释引入依赖注入。依赖分析是在编译的时候进行的。优点:
- 增加了在程序运行前发现错误的可能性。
- 编译生成的代码可读性更高,便于debug。
缺点:
- 降低了灵活性。
- 不能对private变量注入依赖。
dagger注释
@inject:inject主要有有两个作用。
一个是用在构造函数上,通过标记构造函数,使得dagger2能够在需要这个类的时候来找到这个构造函数并产生一个实例,从而提供依赖。对于当前project里的class可以使用这中方法提供依赖。
另外一个作用就是标记在需要依赖的变量让dagger2为其提供依赖。
@provide: 用provide来标注一个方法,该方法可以在需要提供依赖时被调用,从而把预先提供好的对象当做依赖提供给@inject的变量。provide主要用于标注module里的方法。
@module 是用来提供依赖的。@inject只能为project内的class提供依赖,但是对于一些第三方library中的class,因为无法更改代码,就无法使用@inject提供依赖。module可以给不能修改源码的class提供依赖。当然project内的class也可以通过module提供依赖。
@component component是依赖提供方和需求方之间的桥梁。
dagger注入依赖原理
我们有两种方式可以提供依赖,一个是注解了@Inject的构造方法,一个是在Module里提供的依赖,那么Dagger2是怎么选择依赖提供的呢,规则是这样的:
步骤1:查找Module中是否存在创建该类的方法。
步骤2:若存在创建类方法,查看该方法是否存在参数
步骤2.1:若存在参数,则按从步骤1开始依次初始化每个参数
步骤2.2:若不存在参数,则直接初始化该类实例,一次依赖注入到此结束
步骤3:若不存在创建类方法,则查找Inject注解的构造函数,看构造函数是否存在参数
步骤3.1:若存在参数,则从步骤1开始依次初始化每个参数
步骤3.2:若不存在参数,则直接初始化该类实例,一次依赖注入到此结束
概括一下就是从注解了@Inject的对象开始,从Module和注解过的构造方法中获得实例,若在获取该实例的过程中需要其他类的实例,则继续获取被需要类的实例对象的依赖,同样是从Module和标注过的构造方法中获取,并不断递归这个过程直到所有被需要的类的实例创建完成,在这个过程中Module的优先级高于注解过的构造方法。