Dagger 2
依赖注入框架
资料
Github
官网
API
文档翻译
导入
- 配置模组的 build.gradle
dependencies {
dependencies {
compile 'com.google.dagger:dagger:2.7'
annotationProcessor 'com.google.dagger:dagger-compiler:2.7'
}
}
基本用法
构造
@Inject
- 可以注入成员变量、构造方法、成员方法
// 在 Bean 的构造方法上添加注解 @Inject,只能注解一个构造方法,编译后生成 Xxx_Factory
@Inject
public Dog() {}
// 创建接口 @Component,作为注入器,可以是接口或者抽象类,编译时产生类 DaggerXxxComponent
@Component
public interface DogComponent {
// 注入方法,方法名任意,不能使用子类,编译后生成 Xxx_MembersInjector
void inject(MainActivity activity);
}
// 在需要注入的成员变量上添加注解 @Inject,不能私有
@Inject
Dog dog;
// 在编译生成代码后,注入
DaggerDogComponent.create().inject(this);
模组
@Module
、@Provides
-
@Inject
和@Provides
组成对象表,需注入对象时在表中查询 -
@Module
的优先级高于@Inject
,优先通过@Module
生成实例
// 在 Module 类上添加注解 @Module,编译后生成 XxxModule_ProvideXxxFactory
@Module
public class CatModule {
@Provides // 在生成方法上添加注解 @Provides
Cat provideCat(String name) {
return new Cat(name);
}
@Provides
String provideString() {
return "cat";
}
}
// 在 Component 接口上添加注解 @Component,参数(modules)指向Module
@Component(modules = CatModule.class)
public interface CatComponent {
void inject(MainActivity activity);
}
@Inject
Cat cat;
DaggerCatComponent.create().inject(this);
注入器
@Component
- 如果你的
@Component
不是顶层的类型,那生成的component的名字将会包含它的封闭类型的名字,通过下划线连接。
@Module
public class SheepModule {
@Provides
Sheep provideSheep(String name) {
return new Sheep(name);
}
}
@Module
public class NameModule {
private String name;
public NameModule(String name) { // 参数可以通过 Module 的构造方法传入
this.name = name;
}
@Provides
String provideString() {
return name;
}
}
// 在 Component 接口上添加注解 @Component,参数(modules)指向多个 Module
@Component(modules = {SheepModule.class, NameModule.class})
public interface SheepComponent {
void inject(MainActivity activity);
// 公开可见的对象图表,编译后会生成对应的方法
Sheep newSheep();
}
@Inject
Sheep sheep;
// 在生成代码后,构建注入器添加 Module 和参数
SheepComponent component = DaggerSheepComponent.builder().nameModule(new NameModule("sheep")).build();
component.inject(this); // 注入,注入标注 @Inject 的对象
Sheep sheep = component.newSheep(); // 调用方法,获取对象
作用域
@Scope
、@Singleton
、@Reusable
(测试)
-
@Scope
作用域,在作用域内保持单例,单例对象保存于Component中 -
@Singleton
单例,为@Scope
的实现注解 -
@Reusable
重用,首次使用缓存起来重复使用 - 可添加在
@Provides
标注的方法上或实例类上 - Components可以有多种域注解,表明这些注解是同一个域的别名
// 自定义注解@DefaultScope
@Scope
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface DefaultScope {
}
@Module
public class HorseModule {
@Provides @DefaultScope // 添加注解 @DefaultScope
Horse provideHorse() {
return new Horse();
}
}
@DefaultScope // 添加注解 @DefaultScope
@Component(modules = HorseModule.class)
public interface HorseComponent {
void inject(MainActivity activity);
Horse newHorse();
}
@Inject
Horse horse;
// 注入的对象和获取的对象为同一对象,单例
HorseComponent component = DaggerHorseComponent.builder().build();
component.inject(this);
Horse horse = component.newHorse();
限定符
@Qualifier
、@Named
-
@Qualifier
限定符 -
@Named
命名,为@Qualifier
的实现注解
// 自定义限定符 @RedPig 和 @BlackPig
@Qualifier
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface RedPig {
}
@Qualifier
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface BlackPig {
}
@Module
public class PigModule {
@RedPig // 添加限定符
@Provides
Pig provideRedPig() {
return new Pig("Red Pig");
}
@BlackPig // 添加限定符
@Provides
Pig provideBlackPig() {
return new Pig("Black Pig");
}
}
@Component(modules = PigModule.class)
public interface PigComponent {
void inject(MainActivity activity);
@RedPig // 公开的对象表,添加限定符
Pig newRedPig();
@BlackPig // 公开的对象表,添加限定符
Pig newBlackPig();
}
@RedPig // 添加限定符
@Inject
Pig redPig;
@BlackPig // 添加限定符
@Inject
Pig blackPig;
DaggerPigComponent.create().inject(this);
加载
Lazy
、Provider
-
Lazy
延迟加载,首次使用才注入 -
Provider
重新加载,每次重新注入 -
Lazy
不等于单例
@Inject
Lazy duckLazy;
@Inject
Provider duckProvider;
T get() // 获取对象
进阶用法
依赖
@Component(dependencies)
- 相互独立的 Component,被依赖的 Component 公开对象表
@DefaultScope
@Component(modules = HorseModule.class)
public interface HorseComponent {
void inject(ADActivity activity);
// 依赖必须有公开的对象表
Horse newHorse();
}
@MareScope // 作用域,和 HorseComponent 的不同
@Component(modules = MareModule.class, dependencies = HorseComponent.class)
public interface MareComponent {
Mare newMare(); // MareModule 提供的对象表
Horse newHorse(); // HorseComponent 提供的对象表
}
MareComponent component = DaggerMareComponent.builder().horseComponent(DaggerHorseComponent.create()).build();
Mare mare = component.newMare();
Horse horse = component.newHorse();
继承
@Subcomponent
、@Subcomponent.Builder
- Component 结成一个整体,父 Component 不须公开对象列表,子 Component 自动获取所有的对象表
- 子 Component 具备了父 Component 拥有的 Scope,也具备了自己的 Scope。不同作用域的对象存在各自的 Component 中
// 父 Component,无须公开对象表,子自动获取
@Singleton
@Component(modules = DonkeyModule.class)
public interface DonkeyComponent {
// 声明子 Component 的获取方法,返回类型是 Subcomponent 类,方法名随意,参数是这个 Subcomponent 需要的 Modules,如 Modules 不用传参,可省略
MuleComponent muleComponent(MuleModule module);
}
@MuleScope // 子 Component 的 Scope 范围小于父 Component
@Subcomponent(modules = MuleModule.class)
public interface MuleComponent {
// 父 Component 不能注入容器,子 Component 一起注入
void inject(AHActivity activity);
}
@Inject
Donkey donkey;
@Inject
Mule mule;
DonkeyComponent donkeyComponent = DaggerDonkeyComponent.create();
MuleComponent muleComponent = donkeyComponent.muleComponent(new MuleModule()); // 通过父获取子
muleComponent.inject(this); // 子完成所有注入
多重绑定
@IntoSet
、@ElementsIntoSet
、@IntoMap
(测试)
@Module
public class OneModule {
@IntoSet // 向 Set 返回一个元素
@Provides
static Pig provideOne(@RedPig Pig pig) {
return pig;
}
}
@Module
public class TwoModule {
@ElementsIntoSet // 向 Set 返回多个元素
@Provides
static Set provideTwo(@BlackPig Pig pig1, @BlackPig Pig pig2) {
return new HashSet(Arrays.asList(pig1, pig2));
}
@ElementsIntoSet
@Provides
static Set primeEmpty() {
return Collections.emptySet(); // 向 Set 返回空元素
}
}
@Component(modules = {PigModule.class, OneModule.class, TwoModule.class})
public interface SetComponent {
Set get(); // 显露的对象表
}
Set pigs = DaggerSetComponent.create().get(); //获取到一个 Set