简书: https://www.jianshu.com/p/9703a931c7e7 dagger 单例

无module的使用方式: 只需要在依赖的类和Component类添加@Singleton即可 有module的使用方式: Component必须添加@Singleton标注,然后再根据需要给Module中@provides标注的方法再标注上@Singleton

@Singleton:确定生成的类为单列,也就是确定对象的活动时间,属于全局单例,作用在使用@Provides方法上,也要配置到@Component中

@Scope:范围,在Dagger2中应用就是确定对象的生命周期,也就是确定对象的存活范围。是一个局部变量的注释,其活动范围在注释修饰的@Component内

Inject,Component,Module,Provides,Scope,Qualifier Inject,即注入,该注解标示地方表示需要通过DI框架来注入实例。Inject有三种方式,分别是Constructor injection、Fields injection、Methods injection。申明了Inject之后,会从注入框架中去查找需要注入的类实例,然后注入进来,也就是通过Component去查找

Qualifier 如果类实例创建有多种相同的方式,就需要通过标签tag来区分之,并在注入的时候通过标签来区分。

Module Module 是类实例提供的工厂模式,Module里面的方法基本都是创建类实例的方法 Dagger2中就有2个维度可以创建类实例: 通过用Inject注解标注的构造函数来创建(简称Inject维度) 通过工厂模式的Module来创建(简称Module维度)

Component Component 要解决的问题就是Inject的实例从哪里来,所以它承担的就是一个连接器的作用。Component需要引用到目标类的实例,Component会查找目标类中用Inject注解标注的属性,查找到相应的属性后会接着查找该属性对应的用Inject标注的构造函数(这时候就发生联系了),剩下的工作就是初始化该属性的实例并把实例进行赋值

Scope Dagger2中Scope关心的问题就是类实例的生命周期

依赖关系(dependencies) 被依赖的 Component 需要把暴露的依赖实例用显式的接口声明,如上面的Car car(),我们只能使用朋友愿意分享的东西。 依赖关系中的 Component 的 Scope 不能相同,因为它们的生命周期不同。

依赖Component(PresenterComponent) 仅继承 被依赖Component(AppComponent) 中显示提供的依赖,如果不提供,则无法使用@Inject注入被依赖的Component(AppComponent)中的对象

继承关系

SubComponent 必须显式地声明 Subcomponent.Builder,parent Component 需要用 Builder 来创建 SubComponent

SubComponent 编译时不会生成 DaggerXXComponent,需要通过 parent Component 的获取 SubComponent.Builder 方法获取 SubComponent 实例

继承关系中不用显式地提供依赖实例的接口,SubComponent 继承 parent Component 的所有依赖

依赖关系 vs 继承关系 相同点:

两者都能复用其他 Component 的依赖 两个拥有依赖关系的 Component 是不能有相同 @Scope 注解的!使用@SubComponent 则可以使用相同的@Scope注解

区别:

依赖关系中被依赖的 Component 必须显式地提供公开依赖实例的接口,而 SubComponent 默认继承 parent Component 的依赖。 依赖关系会生成两个独立的 DaggerXXComponent 类,而 SubComponent 不会生成 独立的 DaggerXXComponent 类。

Lazy (延迟注入) 有时我们想注入的依赖在使用时再完成初始化,加快加载速度,就可以使用注入Lazy<T>。只有在调用 Lazy<T> 的 get() 方法时才会初始化依赖实例注入依赖 public class Man { @Inject Lazy<Car> lazyCar; public void goWork() { lazyCar.get().go(); // lazyCar.get() 返回 Car 实例 } }

Provider 注入 有时候不仅仅是注入单个实例,我们需要多个实例,这时可以使用注入Provider<T>,每次调用它的 get() 方法都会调用到 @Inject 构造函数创建新实例或者 Module 的 provide 方法返回实例 public class CarFactory { @Inject Provider<Car> carProvider;

public List<Car> makeCar(int num) {
    ...
    List<Car> carList = new ArrayList<Car>(num);
    for (int i = 0; i < num; i ++) {
        carList.add(carProvider.get());
    }
    return carList;
}

}

Qualifier(限定符) 试想这样一种情况:如果Module提供了两个生成car实例的 provide 方法,Dagger 2 在注入car实例到 Man 中时应该选择哪一个方法呢?

@Lazy 和 @Provider

首先是他们共同的作用

相当于提供了一个工厂,直到使用时(调用get),才会真正生成这个对象。

那么Lazy和Provider有什么区别呢?

如果使用Lazy,每次调用都会是同一个对象,如果使用Provider,返回的对象取决于@Provides方法的实现(如果添加@Singletone等那么也会是单例,否则不是。)

Dagger2:module中需要参数传递 @Component(modules = BaseModule.class) public interface BaseComponent { void inject(MainActivity mainActivity);

@Component.Builder
interface Builder {
	//返回值必须是Builder
    @BindsInstance
    Builder activity(@Nullable FragmentActivity activity);//传递参数fragmentActivity

    @BindsInstance
    Builder fragment(@Nullable Fragment fragment);//传递参数fragment  Nullable:可以传递null

    BaseComponent build();
}

}

@Module public final class BaseModule { @Named("Activity")//区分注入时创建的是哪种类型对象 @Provides RxPermissions provideARxPermissions(@Nullable FragmentActivity fragmentActivity) { if (fragmentActivity == null) return null; return new RxPermissions(fragmentActivity); }

@Named("fragment")//区分注入时创建的是哪种类型对象
@Provides
RxPermissions provideFRxPermissions(@Nullable Fragment fragment) {
    if (fragment == null) return null;
    return new RxPermissions(fragment);
}

}

public class MainActivity extends AppCompatActivity { @Named("Activity")//创建类型activity的对象 @Inject RxPermissions rxPermissions;

@Named("fragment")
RxPermissions rxPermissionsF;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    DaggerBaseComponent.builder().activity(this).fragment(null).build().inject(this);
    Logger.d("rxPermissions:" + rxPermissions);
    Logger.d("rxPermissionsF:" + rxPermissionsF);
}

}