Dagger
依赖注入(Dependency Injection),简称DI,又叫控制反转(Inversion of Control),简称IOC
当一个类的实例需要另一个类的实例,在传统的设计中,通常由调用者来创建被调用者的实例,然而依赖注入的方式,创建被调用者不再由调用者创建实例,创建被调用者的实例的工作由IOC容器来完成,然后注入到调用者。因此也被称为依赖注入
- API1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31public @interface Component { 
 Class<?>[] modules() default {};
 Class<?>[] dependencies() default {};
 @Target(TYPE)
 @Documented
 @interface Builder {}
 }
 public @interface Subcomponent {
 Class<?>[] modules() default {};
 @Target(TYPE)
 @Documented
 @interface Builder {}
 }
 public @interface Module {
 Class<?>[] includes() default {};
 @Beta
 Class<?>[] subcomponents() default {};
 }
 public @interface Provides {
 }
 public @interface MapKey {
 boolean unwrapValue() default true;
 }
 public interface Lazy<T> {
 T get();
 }
- @Inject声明依赖注入构造方法,自动请求参数并调用构造方法 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- class Thermosiphon implements Pump { 
 private final Heater heater;
 @Inject
 Thermosiphon(Heater heater) {
 this.heater = heater;
 }
 ...
 }
- @Inject fields 实例化成员变量 
 如果你的类有@Inject成员变量,但是没有@Inject构造方法,Dagger会注入这些变量,但是不会创建新的对象。所有添加@Inject无参的构造函数让Dagger也可以创建对象,也可以@Inject method(),当然Field,Constructor是首选。- 1 
 2
 3
 4
 5- class CoffeeMaker { 
 @Inject Heater heater;
 @Inject Pump pump;
 ...
 }
- @Inject不足 - 1 
 2
 3
 4- 类中只能包含一个@Inject constructor 
 接口,抽象类是没有构造方法的
 第三方库提供的类,它们的构造方法不能被注解
 有些类需要灵活选择初始化的配置,而不是使用一个单一的构造方法
- @Provides 可以满足上面的依赖性,但是必须属于一个Module,有一个惯例方法前缀加provide,类后缀加Module - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- @Module 
 class DripCoffeeModule {
 @Provides static Heater provideHeater() {
 return new ElectricHeater();
 }
 @Provides static Pump providePump(Thermosiphon pump) {
 return pump;
 }
 }
- @Component 在接口中,传入Module,完成接口和类的注入,将CoffeeShop 通过DripCoffeeModule注入到MainActivity中 
 @Component中使用modules,表明该Component在哪些注入的Module中查找依赖
 @Component中使用dependencie,表明该Component在哪些注入的Component中查找依赖
 添加注入方法,一般使用inject
 可以声明方法,提供注入的实例- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18- @Component(modules = DripCoffeeModule.class) 
 interface CoffeeShop {
 CoffeeMaker maker();
 }
 CoffeeShop coffeeShop = DaggerCoffeeShop.builder()
 .dripCoffeeModule(new DripCoffeeModule())
 .build();
 //如果@Component不是在类的上方,生成组件时需要添加下划线
 class Foo {
 static class Bar {
 @Component
 interface BazComponent {}
 }
 }
 DaggerFoo_Bar_BazComponent
- 如果所有的依赖关系都可以在不需要实例对象的情况下创建,那么可以使用builder(),也可以使用crete()创建实例,对于所有的@Provides方法都是静态的Module,可以不需要考虑builder - 1 - CoffeeShop coffeeShop = DaggerCoffeeShop.create(); 
- 针对在MainActivity中的依赖注入 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62- public class Car { 
 @Inject
 public Car() {
 }
 public String show() {
 return String.valueOf(1);
 }
 }
 @Component
 public interface MainActivityComponent {
 void inject(MainActivity activity);
 }
 public class MainActivity extends AppCompatActivity {
 @Inject
 Car car;
 protected void onCreate(@Nullable Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 // 先编译一次crtl+F9
 DaggerMainActivityComponent.create().inject(this);
 String show = car.show();
 Toast.makeText(MainActivity.this, show, Toast.LENGTH_SHORT).show();
 }
 }
 //Water 抽象类,@Inject无法提供实例
 @Inject
 public Car(Water water) {
 }
 
 //清除子类@Inject
 //@Inject
 public HotWater(){
 }
 // @Inject
 public CoolWater(){
 }
 /**
 *@Module标记在类上面
 *@Provodes标记在方法上
 *表示可以通过这个方法获取依赖
 */
 @Module
 public class WaterModule {
 @Provides
 Water provideWater(){
 return new HotWater();
 }
 }
 /**
 * 在Component中指定Module
 */
 @Component(modules = WaterModule.class)
 public interface MainActivityComponent {
 void inject(MainActivity mainActivity);
 }
- @Module需要和@Provide是需要一起使用的时候才具有作用的,并且@Component也需要指定了Module
 @Module是告诉Component,可以从这里获取依赖对象。Component就会去找被@Provide标注的方法,相当于构造器的@Inject可以提供依赖,@Component可以指定多个@Module的
- Component可以包含多个Module或者Component,这样Component获取依赖时候会自动从多个Module中查找获取,但是,Module间不能有重复方法 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18- 在Component中的modules属性中注入多个Module 
 @Component(modules={ModuleA.class,ModuleB.class,...})
 public interface FruitComponent{
 ...
 }
 在Component中的dependencies属性中注入多个依赖的Component
 @Component(dependencies={ComponentA.class,ComponentB.class,...})
 public interface FruitComponent{
 ...
 }
 在Module中注入多个Module
 @Module(includes={ModuleA.class,ModuleB.class,...})
 public class FruitModule{
 ...
 }
- 注入的Module,不管是属于Component本身还是注入的Module的依赖,如果其构造函数为有参构造函数,必须进行初始化 - 1 
 2
 3- DaggerFruitComponent.builder() 
 .orangeModule(new OrangeModule(new OrangeBean("贡菊", 6.88, "江西南昌")))
 .build();
- 依赖规则 
 步骤1:查找Module中是否存在创建该类的方法。- 步骤2:若存在创建类方法,查看该方法是否存在参数 
 步骤2.1:若存在参数,则按从步骤1开始依次初始化每个参数
 步骤2.2:若不存在参数,则直接初始化该类实例,一次依赖注入结束- 步骤3:若不存在创建类方法,则查找Inject注解的构造函数,看构造函数是否存在参数 
 步骤3.1:若存在参数,则从步骤1开始依次初始化每个参数
 步骤3.2:若不存在参数,则直接初始化该类实例,一次依赖注入结束
- 在Component中,可以声明方法,比如makeApple(),直接提供注入对象实例。DaggerFruitComponent针对每一个@Provides方法创建Provider\<T>实例。在调用makeApple()方法时,实际上是调用的相应Provider的get()方法,获取相应的实例 - 1 
 2
 3- public AppleBean makeApple() { 
 return provideAppleProvider.get();
 }
- 依赖对象的注入源应该是有两个,一是Module中的@Provides方法,二是使用@Inject注解的构造函数 
- 单例@Singleton,可以做文档注释,提醒是线程安全 - 1 
 2
 3- @Provides @Singleton static Heater provideHeater() { 
 return new ElectricHeater();
 }
- @Qualifier是限定符,而@Named则是基于String的限定符,容易写错,推荐@Qualifier 自定义注解 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- @Provides 
 @CoolQualifier
 // @Named("Cool")
 Water provideCoolWater() {
 return new CoolWater();
 }
 // 另外的一种方式,这里Water是抽象类,可以考虑其他对象Light灯光
 // @Provides
 // Water providePot(@CoolQualifier Water w) {
 // return new Water(w);
 // }
- @Component与@SubComponent - Car - 1 
 2
 3
 4
 5- @Inject 
 public Car(Water water) {
 this.water = water;
 oil = new Oil();
 }
- WaterComponent - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- /** 
 * @Module标记在类上面
 * @Provodes标记在方法上 表示可以通过这个方法获取依赖
 */
 @Component(modules = WaterModule.class)
 public interface WaterComponent {
 @HotQualifier
 Water getHotWater();
 @CoolQualifier
 Water getCoolWater();
 }
- CarModule - 1 
 2
 3
 4
 5
 6
 7- @Module 
 public class CarModule {
 @Provides
 Car provideCar(@CoolQualifier Water water){
 return new Car(water);
 }
 }
- CarComponent - 1 
 2
 3
 4
 5
 6
 7
 8- /** 
 * @Module标记在类上面
 * @Provodes标记在方法上 表示可以通过这个方法获取依赖
 */
 @Component(modules = CarModule.class, dependencies = WaterComponent.class)
 public interface CarComponent {
 Car getCar();
 }
- MainActivityComponent - 1 
 2
 3
 4- @Component(dependencies = CarComponent.class) 
 public interface MainActivityComponent {
 void inject(MainActivity mainActivity);
 }
- MainActivity - 1 
 2
 3
 4
 5
 6
 7- DaggerMainActivityComponent.builder() 
 .carComponent(DaggerCarComponent.builder()
 .waterComponent(DaggerWaterComponent.create())
 .build())
 .build()
 .inject(this);
 Log.e(TAG, car.show());
- CarComponent依赖WaterComponent,将WaterComponent的引用传递给CarComponent,这样CarComponent就可以使用WaterComponent中的方法。
 在DaggerCarComponent中的getCar()方法,waterComponent.getCoolWater()获取Water
- 通过@SubComponent实现 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14- @Component(modules = WaterModule.class) 
 public interface WaterComponent {
 CarComponent plus(CarModule carModule);
 }
 @Subcomponent(modules = CarModule.class)
 public interface CarComponent{
 MainActivityComponent plus();
 }
 @Subcomponent
 public interface MainActivityComponent {
 void inject(MainActivity mainActivity);
 }
- Component和SubComponent区别 - 1 
 2
 3
 4- Component dependencies 能单独使用,而Subcomponent必须由Component调用方法获取。 
 Component dependencies 可以很清楚的得知他依赖哪个Component, 而Subcomponent不确定
 使用上的区别,Subcomponent就像这样DaggerAppComponent.plus(new SharePreferenceModule());
 使用Dependence可能是这样DaggerAppComponent.sharePreferenceComponent(SharePreferenceComponent.create())
 
- @Scope和@Singleton 
 @Scope管理依赖的生命周期,@Scope对某类注解后,其作用的核心应该是注入器的控制,注入实例时,控制注入器调用缓存的实例还是重新实例,自定义注解,而@Singleton是@Scope默认实现
 如果有类注入实例的类被@Scope注解,那么其Component必须被相同的Scope注解- 1 
 2
 3
 4- @Scope 
 @Documented
 @Retention(RUNTIME)
 public @interface Singleton {}
- 依赖实例的注入来源是@Provides方法时,@Provides方法必须被@Scope注解;如果依赖实例的注入来源是@Inject注解的构造函数时,实例类必须被@Scope注解。这样@Scope注解才会有效。也就是说,@Scope实际上是对注入器的控制 - Scope控制的实例的注入器是当前Component之内的实例注入器,而不会影响其他的Component中的实例注入器 
- 更好的管理Component之间的组织方式,用自定义的Scope注解标注这些Component,检查有依赖关系或包含关系的Component,若发现Component没有用自定义Scope注解标注,则会报错 
- 编译器会检查 Component管理的Modules,标注Component的自定义Scope注解与Modules中的标注创建类实例方法的注解不一样会报错
 
- 单例实例 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20- @Inject 
 Car car1;
 //可以注入多个Car,但是重新创建了一个依赖
 @Inject
 Car car2;
 //使用单例,@Singleton
 @Module
 public class CarModule {
 @Provides
 @Singleton
 Car provideCar(@CoolQualifier Water water){
 return new Car(water);
 }
 }
 @Singleton
 @Component(modules = CarModule.class, dependencies = WaterComponent.class)
 public interface CarComponent {
 Car getCar();
 }
- 编译报错 - 1 
 2- Error:(16, 1) 错误: com.willkernel.www.daggerdemo.component.MainActivityComponent (unscoped) cannot depend on scoped components: 
 @Singleton com.willkernel.www.daggerdemo.component.CarComponent
- 在Component中指定Module
 MainActivityComponent依赖CarComponent
 而dagger2规定使用单例的Component,子Component也必须标注@Scope
 但是不能标注@Singleton,不允许,单例依赖单例不符合设计原则
 需要自定义一个@Scope,例如ActivityScope
 @Singleton 需要在@Provide和@Component,还有MainActivityComponent中使用@Scope
 才能够顺利编译,保持局部单例
- 可以注入多个Car,但是重新创建了一个依赖,使用单例后两个地址一样,
 但是在其他Activity中,地址又不一样,属于局部单例,在其他Activity重新
 创建了注入器Component,所以Car对象的地址改变了
- Dagger正确使用单例 
 依赖在Component中是单例的(供该依赖的provide方法和对应的Component类使用同一个Scope注解)
 对应的Component在App中只初始化一次,每次注入依赖都使用这个Component对象(在Application中创建该Component)
- App - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15- public class App extends Application { 
 private CarComponent carComponent;
 @Override
 public void onCreate() {
 super.onCreate();
 carComponent = DaggerCarComponent.builder()
 .waterComponent(DaggerWaterComponent.create())
 .build();
 }
 public CarComponent getCarComponent() {
 return carComponent;
 }
 }
- SecondActivity - 1 
 2
 3
 4
 5
 6
 7
 8- @Inject 
 Car car3;
 DaggerSecondActivityComponent.builder()
 .carComponent(((App) getApplication()).getCarComponent())
 .build()
 .inject(this);
 Log.e(TAG, "car3=" + car3.hashCode());
- 也可以通过ApplciationScope使用单例 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25- @Scope 
 @Retention(RUNTIME)
 public @interface ApplicationScope {
 }
 public class App extends Application{
 @Inject
 Car car;
 
 @Override
 public void onCreate() {
 super.onCreate();
 DaggerAppComponent.builder().carComponent(DaggerCarComponent.builder() .waterComponent(DaggerWaterComponent.create()).build())
 .build()
 .inject(this);
 }
 
 public Car getCar() {
 return car;
 }
 
 
 在SecondeActivity中引用
 car6=((App)getApplication()).getCar();
 Log.e(TAG, "car6=" + car6.hashCode());
- MapKey - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29- @Component(modules = MapKeyModule.class) 
 public interface MapComponent {
 Map<String, String> mapkey();
 }
 @Module
 public class MapKeyModule {
 @Provides
 @IntoMap
 @TestKey("foo")
 String provideFooKey() {
 return "foo value";
 }
 @Provides
 @IntoMap
 @TestKey("bar")
 String provideBarKey() {
 return "bar value";
 }
 }
 @MapKey(unwrapValue = true)
 public @interface TestKey {
 String value();
 }
 Map<String, String> map = DaggerMapComponent.create().mapkey();
 Log.e(TAG, "map " + map.toString());
- Lazy 
 通过Lazy提供的实例,在@Inject的时候并不初始化,而是使用的时候,主动调用其get方法来获取实例,并且会缓存该对象- 1 
 2
 3
 4
 5- @Inject 
 Lazy<Car> carLazy;
 Car carL = carLazy.get();
 Log.e(TAG, "carL " + carL.show());
- Provider 
 有时您需要注入多个实例列表,而不是注入单个值。可以注入一个Provider- ,而不只是T。 
 当Provider- 每次调用get()方法时,都会执行绑定逻辑并创建一个新的实例,地址不一样,但@Scope注解的类地址是一样的 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14- @CoffeeScope 
 public class CoffeeBean {
 @Inject
 public CoffeeBean() {
 Log.d("test", "Coffee()");
 }
 }
 @Inject
 Provider<CoffeeBean> mCoffeeBeanProvider
 
 CoffeeBean beanA = mCoffeeBeanProvider.get();
 CoffeeBean beanB = mCoffeeBeanProvider.get();
- 多个元素绑定并注入到Set - 将单个元素注入到Set - 1 
 2
 3
 4
 5
 6
 7- @Module 
 class MyModuleA {
 @Provides @IntoSet
 static String provideOneString(DepA depA, DepB depB) {
 return "ABC";
 }
 }
- Set - 注入到Set - 1 
 2
 3
 4
 5
 6
 7- @Module 
 class MyModuleB {
 @Provides @ElementsIntoSet
 static Set<String> provideSomeStrings(DepA depA, DepB depB) {
 return new HashSet<String>(Arrays.asList("DEF", "GHI"));
 }
 }
- 在Component中,表明注入到Set的实例的提供Module,声明setApple()方法,用来提供集合Set - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17- class Bar { 
 @Inject Bar(Set<String> strings) {
 assert strings.contains("ABC");
 assert strings.contains("DEF");
 assert strings.contains("GHI");
 }
 }
 或者
 @Component(modules = {MyModuleA.class, MyModuleB.class})
 interface MyComponent {
 Set<String> strings();
 }
 @Test void testMyComponent() {
 MyComponent myComponent = DaggerMyComponent.create();
 assertThat(myComponent.strings()).containsExactly("ABC", "DEF", "GHI");
 }
 
- 也可以通过Provider<Set - > or Lazy<Set - >来依赖注入实例,但是不能通过Set<Provider - >> 
- 增加限定符@Qualifier - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14- @Module 
 class MyModuleC {
 @Provides @IntoSet
 @MyQualifier
 static Foo provideOneFoo(DepA depA, DepB depB) {
 return new Foo(depA, depB);
 }
 }
 @Module
 class MyModuleD {
 @Provides
 static FooSetUser provideFooSetUser(@MyQualifier Set<Foo> foos) { ... }
 }
- 多个元素绑定并注入到Map 
 在Module中的@Provides方法使用@IntoMap,同时指定该元素的Key(例如@StringKey(“foo”),@ClassKey(Thing.class),@IntKey(12),@LongKey(100L)),没有这个key时,返回null- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27- @Module 
 class MyModule {
 @Provides @IntoMap
 @StringKey("foo")
 static Long provideFooValue() {
 return 100L;
 }
 @Provides @IntoMap
 @ClassKey(Thing.class)
 static String provideThingValue() {
 return "value for Thing";
 }
 }
 @Component(modules = MyModule.class)
 interface MyComponent {
 Map<String, Long> longsByString();
 Map<Class<?>, String> stringsByClass();
 }
 @Test void testMyComponent() {
 MyComponent myComponent = DaggerMyComponent.create();
 assertThat(myComponent.longsByString().get("foo")).isEqualTo(100L);
 assertThat(myComponent.stringsByClass().get(Thing.class))
 .isEqualTo("value for Thing");
 }- 如果key是枚举或其他特定的类,使用@MapKey注解,自定义Key
- 自定义枚举类型,数据包装类key 
 如果不满足指定的返回类型,那么编译时会报错:
 基本数据类型
 String
 Class(参数化类,? extends Number)
 枚举类型
 注解类型
 以上数据类型的数组- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13- enum MyEnum { 
 ABC, DEF;
 }
 
 @MapKey
 @interface MyEnumKey {
 MyEnum value();
 }
 @MapKey
 @interface MyNumberClassKey {
 Class<? extends Number> value();
 }
- 在Module中的@Prvoides使用@IntoMap,并指明key - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14- @Module 
 class MyModule {
 @Provides @IntoMap
 @MyEnumKey(MyEnum.ABC)
 static String provideABCValue() {
 return "value for ABC";
 }
 @Provides @IntoMap
 @MyNumberClassKey(BigDecimal.class)
 static String provideBigDecimalValue() {
 return "value for BigDecimal";
 }
 }
- 注入器Component - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- @Component(modules = MyModule.class) 
 interface MyComponent {
 Map<MyEnum, String> myEnumStringMap();
 Map<Class<? extends Number>, String> stringsByNumberClass();
 }
 @Test void testMyComponent() {
 MyComponent myComponent = DaggerMyComponent.create();
 assertThat(myComponent.myEnumStringMap().get(MyEnum.ABC)).isEqualTo("value for ABC");
 assertThat(myComponent.stringsByNumberClass.get(BigDecimal.class))
 .isEqualTo("value for BigDecimal");
 }
- 组合的MapKey,设置unwrapValue的值为false,这样key值也可以是数组成员,key不唯一指定,可以有多个不同类型的key - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20- @MapKey(unwrapValue = false) 
 @interface MyKey {
 String name();
 Class<?> implementingClass();
 int[] thresholds();
 }
 @Module
 class MyModule {
 @Provides @IntoMap
 @MyKey(name = "abc", implementingClass = Abc.class, thresholds = {1, 5, 10})
 static String provideAbc1510Value() {
 return "foo";
 }
 }
 @Component(modules = MyModule.class)
 interface MyComponent {
 Map<MyKey, String> myKeyStringMap();
 }
- 使用MapKey,需要生成Mykey的静态方法,就需要使用@AutoAnnotation - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15- apt 被annotationProcessor替代 
 apply plugin: 'com.neenbedankt.android-apt'
 classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
 annotationProcessor "com.google.auto.value:auto-value-annotations:1.5"
 implementation "com.google.auto.value:auto-value:1.5"
 
 @AutoAnnotation
 static MyKey createMyKey(String name, Class<?> implementingClass, int[] thresholds) {
 return new AutoAnnotation_MainActivity_createMyKey(name, implementingClass, thresholds);
 }
 
 MyKeyComponent myKeyComponent = DaggerMyKeyComponent.create();
 Log.e(TAG, "myKeyComponent "+myKeyComponent.myKeyStringMap()
 .get(createMyKey("abc", BigDecimal.class, new int[]{1, 2, 4})));
- Mapkey的key在编译期间未知,就不能创建Mapkey的绑定,不过可以先设置绑定Set,再转换为Map绑定 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28- @Module 
 class MyModule {
 @Provides @IntoSet
 static Map.Entry<Foo, Bar> entryOne(...) {
 Foo key = ...;
 Bar value = ...;
 return new SimpleImmutableEntry(key, value);
 }
 @Provides @IntoSet
 static Map.Entry<Foo, Bar> entryTwo(...) {
 Foo key = ...;
 Bar value = ...;
 return new SimpleImmutableEntry(key, value);
 }
 }
 @Module
 class MyMapModule {
 @Provides
 static Map<Foo, Bar> fooBarMap(Set<Map.Entry<Foo, Bar>> entries) {
 Map<Foo, Bar> fooBarMap = new LinkedHashMap<>(entries.size());
 for (Map.Entry<Foo, Bar> entry : entries) {
 fooBarMap.put(entry.getKey(), entry.getValue());
 }
 return fooBarMap;
 }
 }
- Dagger并不会自动注入Map\<Foo,Provider\<Bar>>,也就意味着不会提供一个含有Provider值得Map。如果想要获取一个含有Provider的Map,需要在Map.Entry对象中包含Provider值,那么所获取的Map也就含有Provider - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18- @Module 
 class MyModule {
 @Provides @IntoSet
 static Map.Entry<Foo, Provider<Bar>> entry(
 Provider<BarSubclass> barSubclassProvider) {
 Foo key = ...;
 return new SimpleImmutableEntry(key, barSubclassProvider);
 }
 }
 @Module
 class MyProviderMapModule {
 @Provides
 static Map<Foo, Provider<Bar>> fooBarProviderMap(
 Set<Map.Entry<Foo, Provider<Bar>>> entries) {
 return ...;
 }
 }
 
- 声明多重绑定@Multibinds-annotated,也可以使用@IntoSet,@IntoMap,@ElementsIntoSet,但是必须有一个 - 1 
 2
 3
 4
 5
 6
 7- @Module 
 abstract class MyModule {
 @Multibinds abstract Set<Foo> aSet();
 @Multibinds @MyQualifier abstract Set<Foo> aQualifiedSet();
 @Multibinds abstract Map<String, Foo> aMap();
 @Multibinds @MyQualifier abstract Map<String, Foo> aQualifiedMap();
 }
- Set或Map多重绑定可以声明任意次数而不会发生错误。Dagger从不实现或调用任何@Multibinds方法 
 添加返回空集合的@ElementsIntoSet方法- 1 
 2
 3
 4
 5
 6
 7- @Module 
 class MyEmptySetModule {
 @Provides @ElementsIntoSet
 static Set<Foo> primeEmptyFooSet() {
 return Collections.emptySet();
 }
 }
- 添加子组件方式 - @Component的dependencies属性依赖父组件 - 1 
 2
 3
 4- @Component(modules = OrangeModule.class, dependencies = FruitComponent.class) 
 public interface OrangeComponent {
 ***
 }
- @Module的Subcomponents添加子组件 - 1 
 2
 3
 4
 5- @Module(subcomponents = AppleSubcomponent.class) 
 public class FruitModule {
 ***
 }
 
- @SubComponent声明子组件,需要提供@Subcomponent.Builder接口的Builder,build()来构建子组件 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- @Subcomponent(modules = RequestModule.class) 
 interface RequestComponent {
 RequestHandler requestHandler();
 @Subcomponent.Builder
 interface Builder {
 Builder requestModule(RequestModule module);
 RequestComponent build();
 }
 }
- 添加子组件到父组件,添加子组件类到父组件的@Module的subcomponents属性,然后父组件调用子组件的builder方法 - 1 
 2- @Module(subcomponents = RequestComponent.class) 
 class ServerModule {}
- 父组件的注入器 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21- @Singleton 
 @Component(modules = ServerModule.class)
 interface ServerComponent {
 RequestRouter requestRouter();
 }
 子组件实例注入
 @Singleton
 class RequestRouter {
 @Inject RequestRouter(
 Provider<RequestComponent.Builder> requestComponentProvider) {}
 void dataReceived(Data data) {
 RequestComponent requestComponent =
 requestComponentProvider.get()
 .data(data)
 .build();
 requestComponent.requestHandler()
 .writeResponse(200, "hello, world");
 }
 }
- 子组件和作用域,如果没有作用域的绑定,每次注入都会重新创建独立的对象,但是如果有作用域绑定的对象,在作用域生命周期中绑定的对象实例是同一个 
- 子组件和父组件的作用域不能相同,比父组件的生命周期短,两个子组件有不同的作用域实例,即使他们的作用域注解相同 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16- @Singleton @Component 
 interface RootComponent {
 SessionComponent.Builder sessionComponent();
 }
 @SessionScope @Subcomponent
 interface SessionComponent {
 FooRequestComponent.Builder fooRequestComponent();
 BarRequestComponent.Builder barRequestComponent();
 }
 @RequestScope @Subcomponent
 interface FooRequestComponent {...}
 @RequestScope @Subcomponent
 interface BarRequestComponent {...}
- 封装子组件 
 在不同Service,不同界面,共享某些绑定,但是这些绑定中也有不需要的绑定实例,这时就需要使用子组件,对绑定实例进行细分- 应用ApplicationComponent,注入数据库实例 - 1 
 2
 3
 4
 5- @Singleton 
 @Component(modules = DatabaseModule.class)
 interface ApplicationComponent {
 Database database();
 }
- 数据库模块,子组件为DatabaseComponent - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13- @Module(subcomponents = DatabaseComponent.class) 
 class DatabaseModule {
 @Provides
 @Singleton
 Database provideDatabase(
 @NumberOfCores int numberOfCores,
 DatabaseComponent.Builder databaseComponentBuilder) {
 return databaseComponentBuilder
 .databaseImplModule(new DatabaseImplModule(numberOfCores / 2))
 .build()
 .database();
 }
 }
- 数据库实现类模块 - 1 
 2
 3
 4
 5
 6- @Module 
 class DatabaseImplModule {
 DatabaseImplModule(int concurrencyLevel) {}
 @Provides DatabaseConnectionPool provideDatabaseConnectionPool() {}
 @Provides DatabaseSchema provideDatabaseSchema() {}
 }
- 子组件 - 1 
 2
 3
 4- @Subcomponent(modules = DatabaseImplModule.class) 
 interface DatabaseComponent {
 @PrivateToDatabase Database database();
 }
 
- 抽象工厂方法定义子组件 - 扩展多重绑定 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63- @Subcomponent(modules = DatabaseImplModule.class) 
 interface DatabaseComponent {
 @PrivateToDatabase Database database();
 }
 @Module
 class ParentModule {
 @Provides @IntoMap
 @StringKey("one") static int one() {
 return 1;
 }
 @Provides @IntoMap
 @StringKey("two") static int two() {
 return 2;
 }
 @Provides @IntoSet
 static String a() {
 return "a"
 }
 @Provides @IntoSet
 static String b() {
 return "b"
 }
 }
 @Subcomponent(modules = ChildModule.class)
 interface Child {
 Map<String, Integer> map();
 Set<String> set();
 }
 @Module
 class ChildModule {
 @Provides @IntoMap
 @StringKey("three") static int three() {
 return 3;
 }
 @Provides @IntoMap
 @StringKey("four") static int four() {
 return 4;
 }
 @Provides @IntoSet
 static String c() {
 return "c"
 }
 @Provides @IntoSet
 static String d() {
 return "d"
 }
 }
 Parent parent = DaggerParent.create();
 Child child = parent.child();
 assertThat(parent.map().keySet()).containsExactly("one", "two");
 assertThat(child.map().keySet()).containsExactly("one", "two", "three", "four");
 assertThat(parent.set()).containsExactly("a", "b");
 assertThat(child.set()).containsExactly("a", "b", "c", "d");
- 模块Module作为工厂方法的参数会在编译时报错,重复模块Module在依赖注入获取对象时引用是运行时错误 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21- @Component(modules = {RepeatedModule.class, ...}) 
 interface ComponentOne {
 ComponentTwo componentTwo(RepeatedModule repeatedModule); // COMPILE ERROR!
 ComponentThree.Builder componentThreeBuilder();
 }
 @Subcomponent(modules = {RepeatedModule.class, ...})
 interface ComponentTwo { ... }
 @Subcomponent(modules = {RepeatedModule.class, ...})
 interface ComponentThree {
 @Subcomponent.Builder
 interface Builder {
 Builder repeatedModule(RepeatedModule repeatedModule);
 ComponentThree build();
 }
 }
 DaggerComponentOne.create().componentThreeBuilder()
 .repeatedModule(new RepeatedModule()) // UnsupportedOperationException!
 .build();
 
Dagger Android
- 引入Dagger - 1 
 2
 3
 4
 5
 6
 7- // Dagger dependencies 
 annotationProcessor "com.google.dagger:dagger-compiler:$rootProject.daggerVersion"
 provided 'org.glassfish:javax.annotation:10.0-b28'
 compile "com.google.dagger:dagger:$rootProject.daggerVersion"
 compile "com.google.dagger:dagger-android:$rootProject.daggerVersion"
 compile "com.google.dagger:dagger-android-support:$rootProject.daggerVersion"
 annotationProcessor "com.google.dagger:dagger-android-processor:$rootProject.daggerVersion"
- @Binds 
 注解委托绑定模块的抽象方法,例如绑定Random到SecureRandom模块- 1 - @Binds abstract Random bindRandom(SecureRandom secureRandom); - 是@Provides的替代方法,更高效
- @Binds method
 必须是抽象方法
 必须是一个可以转换为返回值类型的参数,参数是返回值类型的子类或实现类,将返回值类绑定到参数类,将参数暴露为返回值类型,不需要实例化参数对象
 可以有限定符@Qualified和作用域@Scoped1 
 2
 3
 4@Documented 
 @Retention(RUNTIME)
 @Target(METHOD)
 public @interface Binds {}
 
- @ContributesAndroidInjector 
 注解的方法生成的返回值对应的AndroidInjector。该注入器是 dagger.Subcomponent的实现,而且是dagger.Module 的子Component
 用于注解返回具体的Android框架类型(例如:FooActivity、BarFragment、MyService等)的dagger.Module中的无参抽象方法
- BindsInstance 标识组件或子组件的Builder方法,绑定对象到组件中的类 - 1 
 2
 3
 4
 5- @Documented 
 @Retention(RUNTIME)
 @Target(METHOD)
 @Beta
 public @interface BindsInstance {}
- 注入实例 
 由于DispatchingAndroidInjector在运行时由类查找相应的AndroidInjector.Factory,那么,在基类中,实现HasActivityInjector/HasFragmentInjector接口,在相应的声明周期(onCreate()或者onAttach())内调用AndroidInjection.inject()方法,注入相应的实例。所有每个子类都需要做的是绑定相应的@Subcomponent,从而没有必要在每个实例类中调用AndroidInjection.inject()方法。- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16- @Beta 
 public abstract class DaggerActivity extends Activity implements HasFragmentInjector {
 @Inject DispatchingAndroidInjector<Fragment> fragmentInjector;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 AndroidInjection.inject(this);
 super.onCreate(savedInstanceState);
 }
 @Override
 public AndroidInjector<Fragment> fragmentInjector() {
 return fragmentInjector;
 }
 }- 在dagger.android库中,有一些基本类型,对于Appliaction是DaggerApplication,只需重写applicationInjectoer()方法来返回AndroidInjector\<XxApplication>
 Dagger提供的基本类型:
 DaggerActivity
 DaggerFragment
 DaggerService
 DaggerIntentService
 DaggerBroadcastReceiver
 DaggerContentProvider
 
- 在dagger.android库中,有一些基本类型,对于Appliaction是DaggerApplication,只需重写applicationInjectoer()方法来返回AndroidInjector\<XxApplication>
 
     
        