依赖注入
目标类中需要用到其他类,首先需要创建其他类的对象,依赖注入就是不需要我们手动的创建对象,通过技术手段把其他类已经初始化好的对象实例注入到目标类中
一般的我们可以称依赖注入为控制反转.控制反转分为依赖注入和依赖查找,依赖注入比较常用
java注解
也叫元数据.一种代码级别的说明
dagger2中的inject component module provides 含义,有什么用 ?
Inject
用注解来标注目标类中所依赖的其他类,
同样采用注解来标注所依赖的其他类的构造函数,那注解的名字就是inject
Component
Component也是一个注解类,一个类想要是Component,必须用Component注解来标注该类,
并且是接口或者是抽象类
@Component 注入器 连接目标类和依赖实例的桥梁
以@Component标注的类必须是接口或者是抽象类
@component 依赖关系是通过dependencies属性添加
APp必须有一个全局的Component来管理全局实例
工作原理 : Component需要引用到目标类的实例,Component会找目标类中用Inject注解标注的属性,
查找到相应的属性后会接着找该属性对应的用Inject标注的构造函数,就发生联系了,
剩下的工作就是初始化该属性的实例并且把实例进行赋值.我们可以叫他注入器
module
使用场景 :项目中使用到第三方库,这个时候Inject就不能用了
接口不能实例化 ,只能通过实现类实例化,这个时候Inject也不能用了
Module其实就是一个简单的工厂模式,Module里面的方法基本都是创建类实例的方法
Component(管理者)可以通过modules属性加入多个Module
provides
在module中,使用它标注创建实例的方法
执行流程
依赖注入
Module的优先级高于Inject构造函数
步骤1:查找Module中是否存在创建该类的方法。就是用 @Provides 标注的providesXXX的方法
步骤2:若存在创建类方法,查看该方法是否存在参数
步骤2.1:若存在参数,则按从**步骤1**开始依次初始化每个参数
步骤2.2:若不存在参数,则直接初始化该类实例,一次依赖注入到此结束
步骤3:若不存在创建类方法,则查找Inject注解的构造函数,
看构造函数是否存在参数
步骤3.1:若存在参数,则从**步骤1**开始依次初始化每个参数
步骤3.2:若不存在参数,则直接初始化该类实例,一次依赖注入到此结束
如果执行到@inject标注的属性的时候,我们呢就去module中先找provides标注的方法 ,找不到就找在实例类构造前有没有加@inject
可见module的优先级是高于inject构造函数的
Scope 作用域
用处就是Component的组织
更好的管理Component之间的组织方式,不管是依赖方式还是包含方式,都有必要用自定义的Scope注解标注这些Component,这些注解最好不要一样,不一样是为了能更好的体现出
component之间的组织方式,还有编辑器检查依赖关系或者是包含关系的Component,若发现有Component没有用自定义的scope注解标注,就会报错
更好的管理component与module之间的匹配关系,编译器会检查Component管理的Modules,若发现Component的自定义的Scope注解与Modules中的标注创建类实例方法的注解不一样,就会报错
@Scope和@Singleton
@Scope作用域
主要用于component的组织方式
管理Component和Module之间的匹配的关系
提高可读性,见名知意
@Singleton
并没有实现单例的能力 是Scope的一种默认实现
ApplicationComponent单例是由代码控制实现
自定义Scope
以Component组织方式自定义Scope
@Scope
@Retention(RetentionPolicy.RUNTIME)
annotation class ActivityScope
没有作用域的component的不能依赖有作用域的component
@Qualifier 限定符
解决依赖注入迷失(同一个接口有多个实现类,编译报错,分不清楚使用哪一个实现类)
@Named
Qualifier的一种实现方式 ,以名称来区分使用哪种注解实现
自定义Qualifier
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
annotation class ActivityQualifier