一些关于dagger2的理解(一)

转自:http://blog.csdn.net/shareye1992/article/details/51398554

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

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

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

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

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

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

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

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

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

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

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

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



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

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



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

        

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

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


        

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

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


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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值