基本知识概念
依赖关系:如果在 Class A 中,有 Class B 的实例,则称 Class A 对 Class B 有一个依赖。例如 Man 中有用到一个 Car 对象,即 Man 对 Car 有一个依赖。
依赖注入(Dependency Injection,简称 DI):是用于实现控制反转(Inversion of Control,缩写为 IoC)最常见的方式之一,就是将对象实例传入到一个对象中去
依赖注入是一种设计模式,降低了依赖和被依赖对象之间的耦合,方便扩展和单元测试。
控制反转:是面向对象编程中的一种设计原则,用以降低计算机代码之间耦合度。控制反转的基本思想是:借助“第三方”实现具有依赖关系的对象之间的解耦。
一开始是对象 A 对 对象 B 有个依赖,对象 A 主动地创建 对象 B,对象 A 有主动控制权,实现了 Ioc 后,对象 A 依赖于 Ioc 容器,对象 A 被动地接受容器提供
的对象 B 实例,由主动变为被动,因此称为控制反转。注意,控制反转不等同于依赖注入,控制反转还有一种实现方式叫“依赖查找”
Dagger2
Dagger2的作用目的:提供对象实例
1、使用@Inject标注构造函数来提供依赖的对象实例的方法
@Inject有三种情况不能使用
A、接口没有构造函数
B、第三方库的类不能被标注
C、构造函数中的参数必须配置
![](https://img.haomeiwen.com/i10761725/d916094b4f5e1cf4.png)
2、用@Provides标注的方法来提供依赖实例,方法的返回值就是依赖的对象实例,@Provides方法必须在Module中,Module 即用@Module标注的类
Module 是提供依赖的对象实例的另一种方式。
3、Lazy(延迟注入) : 只有在调用 Lazy<T> 的 get() 方法时才会初始化依赖实例注入依赖
4、Provider(多个对象的注入):有时候不仅仅是注入单个实例,我们需要多个实例,这时可以使用注入Provider<T>,每次调用它的 get() 方法都会调用到 @Inject 构造函数创建新实例或者 Module 的 provide 方法返回实例
5、Qualifier(限定符):用于module提供多同个类的多个对象的,限定区分,即:Qualifier(限定符)的作用相当于起了个区分的别名
6、Scope(作用域):是用来确定注入的实例的生命周期的,如果没有使用 Scope 注解,Component 每次调用 Module 中的 provide 方法或 Inject 构造函数生成的工厂时都会创建一个新的实例,而使用 Scope 后可以复用之前的依赖实例,简而言之,就是复用实例
@Scope是元注解,是用来标注自定义注解的
例子:
@Documented
@Retention(RUNTIME)
@Scope
public @interface MyScope {}
关键点:
Scope 注解只能标注目标类、@provide 方法和 Component。Scope 注解要生效的话,需要同时标注在 Component 和提供依赖实例的 Module 或目标类上。Module 中 provide 方法中的 Scope 注解必须和 与之绑定的 Component 的 Scope 注解一样,否则作用域不同会导致编译时会报错
7、Component
Component 管理着依赖实例,根据依赖实例之间的关系就能确定 Component 的关系
依赖关系:
例子:
@ManScope
@Component(modules = CarModule.class)
public interface ManComponent {
void inject(Man man);
Car car(); //必须向外提供 car 依赖实例的接口,表明 Man 可以借 car 给别人
}
@FriendScope
@Component(dependencies = ManComponent.class)
public interface FriendComponent {
void inject(Friend friend);
}
注:因为 FriendComponent 和 ManComponent 是依赖关系,如果其中一个声明了作用域的话,另外一个也必须声明,而且它们的 Scope 不能相同,ManComponent 的生命周期 >= FriendComponent 的。FriendComponent 的 Scope 不能是 @Singleton,因为 Dagger 2 中 @Singleton 的 Component 不能依赖其他的 Component。
继承关系:
例子:
@ManScope
@Component(modules = CarModule.class)
public interface ManComponent {
void inject(Man man); // 继承关系中不用显式地提供暴露依赖实例的接口
}
@SonScope
@SubComponent(modules = BikeModule.class)
public interface SonComponent {
void inject(Son son);
@Subcomponent.Builder
interface Builder { // SubComponent 必须显式地声明 Subcomponent.Builder,parent Component 需要用 Builder 来创建 SubComponent
SonComponent build();
}
}
@SubComponent的写法与@Component一样,只能标注接口或抽象类,与依赖关系一样,SubComponent 与 parent Component 的 Scope 不能相同,只是 SubComponent 表明它是继承扩展某 Component 的。怎么表明一个 SubComponent 是属于哪个 parent Component 的呢?只需要在 parent Component 依赖的 Module 中的subcomponents加上 SubComponent 的 class,然后就可以在 parent Component 中请求 SubComponent.Builder。
8、@BindsInstance
用于再创建Component的时候绑定依赖实例,用以注入
总结:
1、Dagger2 依赖注入,目的就是提供对象,在dagger2提供对象有两种方式@Inject 和 @Module
2、每个需要依赖注入的类,都需要一个Component类
3、Qualifier(限定符):用于module提供多同个类的多个对象的
4、Scope的作用可以让注入的对象复用
5、Component的两种关系:依赖和继承 (Builder和build()的使用)
6、继承关系的实现需要:(1)在 parent Component 依赖的 Module 中的subcomponents加上 SubComponent 的 class;(2)在 parent Component 中提供返回 SubComponent.Builder 的接口用以创建 SubComponent
7、@BindsInstance的使用 被该注解过的方法需要在buider被创建之前调用
网友评论