简书:
https://www.jianshu.com/p/9703a931c7e7
dagger 单例
无module的使用方式:br/>只需要在依赖的类和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
public class Man {br/>@Inject
Lazy
public void goWork() {
lazyCar.get().go(); // lazyCar.get() 返回 Car 实例
}
}
Provider 注入
有时候不仅仅是注入单个实例,我们需要多个实例,这时可以使用注入Provider
public class CarFactory {br/>@Inject
Provider
public List makeCar(int num) {
...
List carList = new ArrayList(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 {br/>@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 {br/>@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);
}
}