一些关于dagger2的理解

来源:互联网 发布:windows如何远程mac 编辑:程序博客网 时间:2024/05/04 21:44

        首先,真实的原理我不准,但是我还是提供我的理解。

        阅读这篇文章希望读者能满足一个假设:不管懂不懂,看过一些其他关于dagger2的文章(因为没图、没代码,不便于直观理解)。

        在别人的文章里,会说“依赖”,“注入”,这当然是专业的说法,但是会让像我这样的新手搞的晕头转向。所以接下来我会用自己喜欢的词来描述,熟悉“依赖”、“注入”概念的请自行比对。

        Dagger这个词的意思是“匕首”,匕首是用来扎的,不是砍;起名肯定是有用意的,也许就是“轻盈附着”的意思,本着“轻盈附着”的概念,于是我有了自己的类比。

        因为dagger2 据说是有生命周期而且和对应View同等周期,所以我将dagger2的一系列理解为一个良性的寄生包群(不是肿瘤),寄主死的时候对应寄生包也就死了。  

        Dagger2 有几个比较主要的标记(正规叫法似乎是:注解)。

        @Module 加在一个普通类头上,这个类就成了一个提供对象的载体,好比一只提供病毒的蚊子,当然了它是允许携带多种病毒的。它的主要作用是:灵活提供对象的一个类,或者说把需要提供的对象独立出来,进行配置。

@Module //@module声明这个类是携带实体的组件,一个“容器”public class BehaviourModule {}

        @Provides (不好意思,我就是病毒)标记在提供对象的方法上。凡是被这个东西标记的方法,它的方法名已经不重要了(不是没有意义),将来对病毒的识别会通过对象类型,而不是通过方法名。注意,通过类型不是通过方法名!!所以类型是重点,如果类型重复,这里还有一个@Named的标签,就是在类型相同时用作区别标识;

@Module //@module声明这个类是携带实体的组件,一个“容器”public class BehaviourModule {    @Named("A") //相同返回值类型时的区别符号    @Provides  //@provides声明以下的类型将被提供出去    public Animal getAnimal(){        return new Tiger();    }    @Provides //同上    public Food getFood(){        return new Meat();    }}

        DaggerXXXComponent 按理说我应该先提到XXXComponent的。因为在代码顺序上是先有XXXcomponent这个接口,然后build工程才出现这个类。我依旧觉得它逻辑在先。这个类就是针对某个Activity或者Fragment的“小寄生包”,它将包含所有在其范围内的“病毒(@provides标记的对象)”,并提供Provider<T>的对象类型,它才是那个具有生命周期的东西。

@Generated("dagger.internal.codegen.ComponentProcessor")public final class DaggerBehaviourComponent implements BehaviourComponent {  private Provider<Animal> getAnimalProvider;//@Provides在这里成为了Provider<T>对象  private Provider<Food> getFoodProvider;//在initialize()会发现跟方法名没有半毛钱关系,只跟返回方法类型有关  private MembersInjector<Behaviour1Activity> behaviour1ActivityMembersInjector;//伴随生命周期对象  private DaggerBehaviourComponent(Builder builder) {      assert builder != null;    initialize(builder);  }  public static Builder builder() {      return new Builder();  }  private void initialize(final Builder builder) {      //没有被@Inject标记使用的对象将不会在这里初始化,略智能    this.getAnimalProvider = BehaviourModule_GetAnimalFactory.create(builder.behaviourModule);    this.getFoodProvider = BehaviourModule_GetFoodFactory.create(builder.behaviourModule);    this.behaviour1ActivityMembersInjector = Behaviour1Activity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), getAnimalProvider, getFoodProvider);  }  @Override  public void inject(Behaviour1Activity activity) {      behaviour1ActivityMembersInjector.injectMembers(activity);  }



        @Component 定义寄生包的接口,它必须是一个接口。标记后面的括号里会指定一个或者多个Module.class,表示它实现时要囊括的虫子。这个接口只要干了两件事:一、将“虫子@module”携带的所有“病毒@provides”放入“寄生包daggerxxxComponent”内;二、内部的唯一一个方法指明谁是寄“主”,也就是说明确了和谁的生命周期是等同的。

@Component(modules={BehaviourModule.class, ArgModule.class}) //添加组件,使用Module内各@providespublic interface BehaviourComponent {    void inject(Behaviour1Activity activity);//伴随的生命周期}



        @Inject 英文本意就是“注入”,他是从“寄生包”注入到“寄主”。理解反之后是如何都想不通的。它就是寄主的叛徒,它会把“寄生包”里相同的病毒直接映射过来(是不是映射我不知道,就是那么个意思,理解就行,别较真),从而不需要再去new,当有变化时也不需要考虑“寄主端”。

        

    @Named("A")// 使用同样标记“A”的对象    @Inject //可以理解为该标记从DaggerBehaviourComponent中拿数据    Animal animal;    @Inject //因为只有一个,不需要@Named标记    Food food;

        综合起来说,Module定义对象提供集,提供由@Provides标注的对象;这几个集将会被xxxComponent接口收录,在自动生成的DaggerXXXComponent类中继承,为@Provides并@inject的对象提供一个Provide<实际对象>的句柄(参照任意一个DaggerxxxComponent的源码都可以发现这一点,同样的“寄主”也会提供一个句柄);在使用@Inject的时候,通过某些原理将Provide<实际对象>赋了过来。


        

        还有一点必须要说的是:在寄主中,实现DaggerxxxComponent的时候,凡是其包含的没有无参构造器(或者说只有有参构造器)的module必须显式的传入该Module对象的实例,否则空指针,参考如下系统生成的build()方法代码:

      public BehaviourComponent build() {        if (behaviourModule == null) { //系统会自动新建        this.behaviourModule = new BehaviourModule();      }      if (argModule == null) {//ArgModule没有无参构造器,系统不会自动添加        throw new IllegalStateException("argModule must be set");      }      return new DaggerBehaviourComponent(this);    }  


        这次是第一版,今天就写到这里,本应该有插图、有源码的,那样才更有助于理解。可是因为是周五晚上了,不想搞那么多,就写到这好了。回头会把插图和源码补上。

        觉得有用,请点个赞,评个论,谢谢啦!
2 0
原创粉丝点击