Dagger 2
依賴注入框架
資料
導入
- 配置模組的 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<T>
、Provider<T>
-
Lazy<T>
延遲加載,首次使用才注入 -
Provider<T>
重新加載,每次重新注入 -
Lazy<T>
不等于單例
@Inject
Lazy<Duck> duckLazy;
@Inject
Provider<Duck> 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<Pig> provideTwo(@BlackPig Pig pig1, @BlackPig Pig pig2) {
return new HashSet<Pig>(Arrays.asList(pig1, pig2));
}
@ElementsIntoSet
@Provides
static Set<Pig> primeEmpty() {
return Collections.emptySet(); // 向 Set 返回空元素
}
}
@Component(modules = {PigModule.class, OneModule.class, TwoModule.class})
public interface SetComponent {
Set<Pig> get(); // 顯露的對象表
}
Set<Pig> pigs = DaggerSetComponent.create().get(); //獲取到一個 Set<T>