一些关于dagger2的理解

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

        阅读这篇文章希望读者能满足一个假设:不管懂不懂,看过一些其他关于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内各@provides
public 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
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

公贵买其鹿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值