Android 常用开源框架源码解析 系列dagger2呆哥兔 依赖注入库

【Android 常用开源框架源码解析 系列dagger2呆哥兔 依赖注入库】落花踏尽游何处,笑入胡姬酒肆中。这篇文章主要讲述Android 常用开源框架源码解析 系列dagger2呆哥兔 依赖注入库相关的知识,希望能为你提供帮助。
一、前言 依赖注入定义     目标类中所依赖的其他的类的初始化过程,不是通过手动编码的方式创建的。 是将其他的类已经初始化好的实例自动注入的目标类中。   “依赖注入”也是面向对象编程的 设计模式 ————-组合的配套使用 作用 :降低程序的耦合,耦合就是因为类之间的依赖关系所引起的 产生场景:在一个对象里去创建另一个对象的实例 问题:过多的类,对象之间的依赖会造成代码难以维护。   不符合开闭原则的对象的引用写法:错误示例:     public class ClassA {           classB b ;             public ClassA (ClassB b ){                 this.b = b;           }     }   通过依赖注入的方式 ,将ClassB对象注入到ClassA中。从而灵活配置ClassA 的属性     public class ClassA{           @Inject           ClassB b;           public ClassA(){...}     }   常见的四种注入方式     1、接口注入             定义ClassBInterface接口,在其内定义setB()函数.ClassAInterface去实现ClassBInterface 接口,在ClassAInterface类中定义了一个ClassBInterface成员变量,并复写setB()函数,最终通过setB()函数完成接口注入操作。                   public interface  ClassBInterface  {                     void  setB(ClassB  b);             }             public class  ClassA  implements  ClassBInterface  {                   ClassB  classB;                     @Override                   public void  setB(ClassB  b) {                           classB  =  b;                   }             }       2、set注入——依赖注入的(核心:外部传递而来)重要方法之一       public class  ClassAset  {               ClassB classb; //定义成员变量             //通过set方法完成注入(对其成员变量的赋值),更加剥离了各个部分的耦合性                     public void  setCalssB(ClassB  b){                             classb  =b;                   }       }        ps:很多时候都是通过     3、通过构造方法注入-常用     public class ClassAConstructor {           //在classA中定义一个ClassB 成员变量           ClassB  classB;               //将ClassB作为参数,传递至ClassA的构造函数中,进行成员变量ClassB的赋值           public ClassAConstructor(ClassB b){                 classB = b;           }     }           4、通过java依赖注解完成方法注入-重点 /** * 对象的组合-在一个类中引用其他对象,容器依赖持有的类的实现 * */ public class  FruitContainer  {         //在FruitContainer类中持有了Banana的引用,从而调用引用类的方法完成某些功能         Banana banana;         //在FruitContainer的构造方法中通过banana构造方法新建了一个banana对象         public  FruitContainer(){               banana  =new  Banana();       } }                           涉及场景:业务需求改变,被持有的类的构造方法进行了改变,那么持有这个类的很多类都有可能需要进行不同长度的改变,造成了代码的很大的耦合性增加,降低了扩展性,是种比较严重的不符合开闭原则的写法   思考:在FruitContainer依赖Banana的实现的情况下,用什么办法在不修改FruitContainer的类情况下,满足Banana或是其内在的构造函数进行了修改。 答:  通过注解的方式 ,注入到宿主类:FruitContainer 类中   public class FruitConainerInject{//类不用关心具体(水果)引用类的实现         添加@Inject,自动完成注入功能————> 这时候并不会完成注入,需要引入注解库并在目标类中调用才完成注入       Fruit f;     public FruitContainerInject(){     //动态注入       } }   小结: 不要在需要依赖的类中通过new 类创建依赖而是通过方法提供的参数注入进来   二、dagger2的使用流程     1、将需要注入的对象的类的构造参数使用@Inject标注,在编译的时候编译器会通知dagger2 实例化该类     2、新建component接口,并在开始使用@Component注解进行注释,自定义void inject()函数,并传入需要依赖注入的对象的类型     3、使用编译器的make project 功能 ,进行编译,在build文件夹内目录下生成Component所对应的类,生成的类的名字格式为“Dagger+自定义的Component名字”     4、在需要注入的目标类(一般是Activity or Fragment之类)中,使用@Inject标注要注入的变量,在初始化时候调用自动生成的Component类的builder().xxModule(xxx).build().自定义inject()方法,完成构建   三、dagger2的基本用法 0、导入       compileOnly ‘org.glassfish:javax.annotation:10.0-b28‘       annotationProcessor ‘com.google.dagger:dagger-compiler:2.5‘       implementation ‘com.google.dagger:dagger:2.5’   导入可能存在的问题: Error:Could not get unknown property ‘classpath‘ for task ‘:app:transformJackWithJackForDebug‘ of type com.android.build…..  

  • 1. 删除project根目录build.gradle中的:  classpath ‘com.neenbedankt.gradle.plugins:android-apt:1.8’  (一般现在都没有)
  • 2.app的build.gradle中,删除apply plugin ‘android-apt‘
  • 3.在app的build.gradle中,dependencies中的 apt ‘com.google.dagger:dagger-compiler:2.1.0‘ 改为 
  • annotationProcessor ‘com.google.dagger:dagger-compiler:2.1.0‘
    1、@Inject 注解     1、标记在需要依赖的变量,dagger2为其提供依赖,并实例化有此注解的类     2、使用在构造函数上,构造函数工厂,通过标记构造函数让dagger2 使用,从而提供相关的依赖 ps:dagger2 通过@Inject标记可以在需要这个类实例的时候,来找到这个构造方法,将相关的实例new出来       (1)、@Inject标记的变量  通过@Inject 标记的变量 ,在make project后会在其build下的source文件夹内的debug,包名下生成: "类名_MembersInjector”文件 @Override public void  injectMembers(Car  instance) {     if  (instance  ==  null) {         throw new  NullPointerException("Cannot inject members into a null reference");   } //通过调用typeProvider.get()函数获取到.type ,在这里type 是通过inject标注的     instance.tyre  =  tyreProvider.get(); } ps:通过@Inject 标记的成员变量不能被命名为private 属性,否则无法获取到     (2)、@Inject标记的构造方法 通过@Inject 标记的构造方法 ,在make project后会在其build下的source文件夹内的debug,包名下生成: "类名_Factory”文件 INSTANCE; @Override public  Tyre  get() {     return new  Tyre(); } public static  Factory< Tyre> create() {     return  INSTANCE; }   依赖注入是依赖的对象实例————> 需要注入的实例属性 新建工厂实例并调用成员属性注入类完成Tyre的实例注入     2、@Component 注解——注入者与被注入者之间的墙梁,more Improtant 用于标注接口 或是 抽象类,可以完成依赖注入的过程。 将@Inject 和@Module 联系起来的墙梁,从@Module中获取依赖并将依赖注入给 @Inject @Component标记的接口或是抽象类,在make project后会在其build下的source文件夹内的debug,包名下生成: "Dagger接口名称”文件   @Component public  interfaceCarComponent  { /**1、参数必须是需要注入依赖的类型,不能是其父类 or 子类 *2、注入接口的方法的返回值 必须是void,命名可以任意但是最好是inject+需要注入依赖的类名,便于识别 **/         voidinjectCar(Car  car);   < ——————将依赖注入到的目标位置 }   private  MembersInjector< Car>   carMembersInjector; private void  initialize(final  Builder  builder) { //通过carMembersInjector查找目标类对应的成员属性注入类,将依赖的属性的工厂实例传入给注入类,完成依赖注入     this.carMembersInjector  =  Car_MembersInjector.create(Tyre_Factory.create()); }   public Car() {       //通过Component以下方法注入car 属性,整个流程       DaggerCarComponent.builder().build().injectCar(this); }         标记了@Inject  的变量,需要配套对其对象的构造方法 进行@Inject的构造方法标记 来确定用何种构造方法完成对象的构建,才能创建完成。最后在构建好的使用了@Component修饰的接口中,在目标类的构造方法中使用Component的builder()方法调用接口中的方法完成整个方法的构建   四、dagger2的源码 DaggerCarComponent.builder().build().injectCar(this); 通过构建者模式完成创建   在build() 方法中完成了DaggerCarComponent 对象的创建: public  CarComponent  build() {     return new  DaggerCarComponent(this); }   private void  initialize(final  Builder  builder) { //调用成员注入器Car_MembersInjector 通过create方法完成carMembersInjector对象的构建     this.carMembersInjector  =  Car_MembersInjector.create(Tyre_Factory.create()); }   injectCar():完成实际的成员变量的注入 @Override public void  injectCar(Car  car) {     carMembersInjector.injectMembers(car); }   injectMembers():在 xx_Factory下完成对象的创建 @Override public void  injectMembers(Car  instance) {     if  (instance  ==  null) {         throw new  NullPointerException("Cannot inject members into a null reference");   }       //最后通过tyreProvider.get()函数完成注入     instance.tyre  =  tyreProvider.get(); }   五、dagger2的常用注解-区别于@Inject   思考:如何需要提供的类构造函数无法修改怎么办?比如引用库 里面的类 无法修改如何解决?   @Module 注解
  •   可以给不能修改的类提供依赖,dagger2 会在该类中寻找实例化某个类所需要的依赖
  • 但需要配合@Provide 注解一起使用
  @Provides 
  • 标注一个Module中的方法,可以使需要提供依赖的时候被调用。
  • 同时,被@Provides注解修饰的方法他的返回值就是依赖对象的实例。
  ps:@Provides注解只能使用在Module当中   1、创建一个用@Module修饰的目标类,和一个@Provides修饰的构建类 @Module public class  CarModule  { //在需要提供依赖的时候被调用         @Provides         static  Car  provideCar(){                 return new  Car();       } }   2、在component 桥梁类里指明modules对应的类字节码对象,是具体哪个module @Component(modules  =  CarModule.class) public interface  CarComponent  {         void  injectCar(Car  car); }   3、make program 后生成 :“CarModule_ProvideCarFactory” 在其内部调用了Module的内部方法函数 创建car对象 @Override public  Car  get() {     return  Preconditions.checkNotNull(             CarModule.provideCar(),  "Cannot return null from a [email  protected] @Provides method"); }   一般依赖注入的初始化使用方法: xxxComponent             .builder()             .xxxModule(new xxxModule(                         view:this, new xxx实现InteractorImpl()) )             .build()             .inject(activity:this); ps:
  • InteractorImpl()是P层 被@Inject的标注方法;
  • 同时 P层的对象 也是被@Inject 标记注解
  • 将Module层 标记为@Module注解
  • 根据需要标注 M层内的方法 @Provieds
  • 添加@Component(modules = xx.class)注解,并在其内定义一个inject(传入xxActivity的Activity对象)函数
    ps:通过provide注解 ,dagger2 会找到被标记了@Provides注解的方法,并调用其构造方法来完成对象的创建   六、dagger2的补充知识     同ButterKnife 依赖注入框架一样 dagger2也是采用了apt代码自动生成技术,注解停留在编译时,不影响性能。       在编译器build 过程中,APT 也就是dagger-compiler 扫描到注解生成对应的class字节码文件比如扫描到@Provide 就会生成对应的 provide_factory ,来再需要被初始化的时候查找响应的构造方法。       (一) 一些常用的dagger2的使用           1、带一个参数的构造参数     示例:                  public class Product(){                 @Inject                 public product(){}           }     public class Factory{           Product product;           @Inject           public Factory(Product product){                 this.product = product;           }     } 解析:在 xxActivity 中进行 inject() 的时候,发现 Factory 的构造函数被 @Inject 标注了且带有一个参数,然后 dagger2 就去寻找 Product 发现它的构造函数也被 @Inject 标注并且无参数,于是 dagger2 把 Product 的实例注入给  xxActivity,然后再去实例化 Factory 的时候用的是已经注入给  xxActivity  的那个 Product 实例。也就是说我们可以这样理解:并不是 Factory 直接实例化 Product,而是  xxActivity  实例化 Product 后交给 Factory 使用的。       2、带Module的Inject方式 以第三方库为OkHttp为例:直接上修改后的代码           @Module           public class HttpActivityModule{                   @Provides                 OkHttpClient  provideOkHttpClient(){                       return new OkHttpClient();                 }           }             @Component (modules =HttpActivityModule.class)     public interface HttpActivityComponent{           void inject(HttpActivity httpActivity);     }           3、带复杂 Module的Inject方式 使用场景:       在使用dagger2的时候传入一些配置,直接使用module的构造参数传入即可。实例化的时候使用的是builder内部类传入需要的值。     Module中其中一个依赖又要依赖另外一个依赖。如果被@Provides标注的方法带有参数,dagger2会自动寻找本Module中其他返回值类型为参数的类型的且被@Provides标注的方法。           @Module           public class HttpActivityModule{                 private int txtSize;                       public  HttpActivityModule(int txtSize){                                   this.txtSize = txtSize;                       }                       @Provides                 OkHttpClient  provideOkHttpClient(){                             OkHttpClient client = new OkHttpClient();                                   client.setTxtSize(this.txtSize);                                   return client;                         }                         @Provides                       RetrofitManager provideRetrofitManager( OkHttpClient client){                             return new RetrofitManager(client);————return new 谁就在Activity中 @Inject谁                                   }                 } 如果本Module中找不到就会去看这个类的构造参数是否被@Inject标注:     public class OkHttpClient {           private int txtSize;           @Inject           public OkHttpClient(){}     }         @Module           public class HttpActivityModule{                 private int txtSize;                 public  HttpActivityModule(int txtSize){                             this.txtSize = txtSize;                   }                     ...                         @Provides                       RetrofitManager provideRetrofitManager( OkHttpClient client){                             return new RetrofitManager(client);————return new 谁就在Activity中 @Inject谁                       }       4、Component 依赖Component 模式     有时候一个Component 跟另外一个Component 所提供的依赖有重复的时候,这时候可以像操作extends关键字一样进行依赖关系的注入       a、dependence 方式                @Component(modules = HttpActivityModule.class)           public interface HttpActivityComponent{                 RetrofitManager provideRetrofitManager();           }                 @Component(dependences =HttpActivityComponent.class)           public interface HttpFragmentComponent{                 void inject(HttpFragment httpFragment);           }     在Activity中的关键代码:             private HttpActivityComponent httpActivityComponent; //实例化component对象                   在onCreate()中:                         httpActivityComponent = DaggerHttpActivityComponent.builder().                                              .httpActivityModule( new HttpActivityModule (this) )                                   .build();             public  HttpActivityComponent  getHttpActivityComponent(){                 return  httpActivityComponent;           }         在对应的fragment中的关键代码:           @Inject           RetrofitManager retrofitManager;                     在onViewCreated()中关键代码:                       HttpActivityComponent  activityComponent=((HttpActivity) getActivity()).getHttpActivityComponent();                       DaggerHttpFragmentCompent                                           .builder()                                           .httpActivityComponent(activityComponent)                                         .build()                                         .inject(this); 小结:     1、在父Component中要显示的写出需要暴露可提供给子Component的依赖      2、在子Component的注解中使用 :(dependences =父类Component.class)     3、在子Component的实例化   void inject(xxx)           b、subComponent 方式  部分代码同a方式一样进行省略操作,展示不同地方:            @Component(modules = HttpActivityModule.class)           public interface HttpActivityComponent{                   HttpFragmentComponent httpFragmentComponent();           }                 @SubComponent  -真实实现inject()           public interface HttpFragmentComponent{                 void inject(HttpFragment httpFragment);           }     在对应的fragment中的关键代码:         HttpActivityComponent  activityComponent=                                     ((HttpActivity) getActivity()).getHttpActivityComponent()                                               .httpFragmentComponent().inject(this);                       subComponent 实现方式总结           1、先定义子Component,使用@SubComponent标注           2、定义父Component,在其中定义获取子Component的方法           3、注意子Component 实例化方式   思考:如果子Component构建时候不是无参的而是有参数的情况,又该如何进行处理呢?       解析重点:子Component构建时候传入参数的话,就需要在Component中使用@Subcomponent.Builder注解(接口or抽象类)    示例:       父Component:           @Component( modules = {AppModule.class})           public interface  AppComponent{                   XxActivityComponent.XxBuilderxxBuiler();           }       子Component:     @Subcomponent ( modules = {XxActivityModule.class})     public interface  XxActivityComponent{           void  inject( XxActivity activity);                   @Subcomponent.Builder                 interface XxBuilder{                       XxBuilder xxActivityModule(XxActivityModile module);                             XxActivityComponent build();                 }     } Module 类:     @Module      public class  AppModule{           @Provides           AppBen provideAppBean(){                   return new AppBean():           }       @Module      public class  XxActivityModule{           private ActivityBean activityBean;           public XxActivityModule (ActivityBean bean){                 this.activityBean = bean;           }           @Provides              ActivityBean provideActivityBean(){                   return this.activityBean;           }     }                    然后看一下在其对应的Application 和Activity 里的实现                   App extends Application{ //applicaation 对应了父Component                 private AppComponent appComponent;                       @Override                        public void onCreate(){                             appcComponent= DaggerAppComponent.create();                         }                       public AppComponent getAppComponent(){                             return appComponent;                       }           }       XxActivity extends AppCompatActivity{                 @Inject                  AppBean appBean;                 @Inject                  ActivityBean activityBean;                   …               ...   onCreate(){                         …                       ((App)getApplication() ) .getAppComponent()                             .xxBuilder()                             .xxActivityModule (new XxActivityModule (new ActivityBean() ) )                             .build()                             .inject (this);                         …           }     小结:           subComponent 实现方式小结:             1、在子Compoonent ,定义一个借口或是抽象类(通常定义为xxBuilder),使用@Subcomponent.Builder() 标注           2、编写返回值 为XxBuilder,方法的参数需要传入参数的XxModule类型           3、编写返回值为当前子Component 的无参方法           4、 父Component 中定义获取子 Component.Builder的方法   (二) dagger2 中有关Scope 作用域     1、无module 的状态           只需要提供依赖的类,以及Component 都添加@Singleton标注           @Singleton           public class Product {                 @Inject                 public Product(){}           }                @Singleton           @Component             public interface Factory{                 void inject(xxActivity activity);           }           在使用的时候,在对应的Activity里进行声明:           @Inject           Product product;           DaggerXxActivityComponent.create().inject)the); ps: 如果使用@Singleton 标注了构造参数 ,或是只标注了提供依赖的类 并没有标注Component类 那么 系统会报以下两种错误:     @Scope annotations are not allowed on @Inject   constructors.Annotate the class instead     @包名 .xxComponent (unscoped) may not reference…@Singleton class  ….     2、有module 的状态               Component 必须添加@Singleton 标注,再根据需要给Module中的@Provides标注的方法再标注上@Singleton            //无参数构造方法           public class Product{           public Product(){}             }           //Component 接口类:           @Singleton           @Component (modules = XxActivityModule.class)           public interface XxActivityComponent{                 void inject(XxActivity activity);             }            @Module     public class XxActivityModule{           @Singleton           @Provides                 Product provideProduct(){                       return new Product():                 }     }       有关Scope 的注意事项:     1、把Scope简单的解释为单例是不科学的。正确的理解应该是:           在某个范围里他是单例(何为作用域呢?可以看作是程序中实例化的Component 的生命周期的长短;         如果在Application里 build的那它的作用域就是整个App的生命周期;           如果在Activity中build的那它的作用域就随着Activity的生命周期保持一致;             )                    2、Scope 只是一个标注 ,只跟它使用的地方及Component实例化的地方有关     3、在Component 依赖Component 的时候,Scope的名字必须不同。       七、dagger2 结合 MVP 模式的小示例片段详解 在普通模式下 使用MVP 模型,P层 和V层 也就是Activity会相互持有对方的引用,如下:   View层 实例代码: public class  PopActivity  extends  AppCompatActivity  implements  xxViewImpl  {         private  xxPresenter  xxxPresenter; @Override       protected void  onCreate(@Nullable  Bundle  savedInstanceState) {               super.onCreate(savedInstanceState);                         ...                 //实例化p层对象,将View传递给P对象,并调用P层方法                 xxxPresenter  =  new  xxPresenter(this);                 xxxPresenter.xxx();       } } Presenter层实例代码: public class  xxPresenter  {         //View层的引用         private  xxViewImpl  mView;           public  xxPresenter(xxViewImpl view) {                 mView  =  view;       }         public void  xxx(){                 //调用model数据层方法,加载数据                 ...                 //回调方法在成功 or 失败时候                 mView.updateUi();       } } 以上实例代码就存在Activity和Presenter 存在一定的耦合程度,如果使用依赖注入的形式的话:     View层伪代码: public class  xxActivity  extends    AppCompatActivity  implements  xxViewImpl{         @Inject          xxPresenter xxxPresenter;           @Override         protected void  onCreate(@Nullable  Bundle  savedInstanceState) {                 super.onCreate(savedInstanceState);                 ...                 //依赖注入框架初始化                 DaggerXXComponent.builder()                                       .XXModule(new  XXModule(this))                               .build()                               .inject(this);                 //调用p层方法                 xxxPresenter.xx*();       } } tips:表明xxPresenter是需要注入到这个Activity中,即表明这个Activity依赖于xxPresenter,但是p对象不能为private修饰符。这里通过new XXModule(this)将view传递到XXModule里,然后XXModule里的provideXXView()方法返回这个View,当去实例化XXPresenter时,发现构造函数有个参数,此时会在Module里查找提供这个依赖的方法,将该View传递进去,这样就完成了presenter里View的注入。   P层伪代码: public class  xxPresenter  {         //View层的引用           xxViewImpl  mView;                     @Inject         public  xxPresenter(xxViewImpl view) {                 mView  =  view;       }         public void  xxx(){                 //调用model数据层方法,加载数据                 ...                 //回调方法在成功 or 失败时候                 mView.updateUi();       } } tips:在P层构造方法添加@Inject注解,表明这个构造方法与Activity中的p层对象建立联系。也就说档某个类被@Inject,就会到这个类中的构造方法中,查找从而完成依赖注入。 注意??:google不推荐直接将P层的构造参数添加注解,更加推荐将P层放到Module里进行管理,因为这样代码更加容易管理。   新建用于链接的墙梁接口     @Component(modules=XXModule.class  ) public interface XXComponent{     void inject(xxActivity activity); } tips:根据Component将前面两项建立联系,并自定义void 返回类型的方法传入需要被注入的类Activity。并进行build项目   @Module注解的伪代码: @Module public class  XXModule  {         final  xxViewImpl  mView;           public  XXModule(xxViewImpl view) {                 mview  =  view;       }         @Provides         XXView  provideXXVIew(){                 return  mView;       } } tips:用来提供依赖,来使得部分没有构造函数的类的依赖,也就是无法手动@Inject的类比如引用库,系统库;     在module类里,在构造方法里将外界传进来的view赋值给声明的成员对象,并通过@Provides注解标注,以providexx开头名称,并返回声明的view对象,该方法是为了提供依赖,可以创建多个不同的方法提供不同依赖     下面通过伪代码实例再研究下其原理性的内容:       在对已经@Inject 修饰过的构造方法进行makeProgram 过程后,会生成xxx_Factory类:         public XXPresenter_Factory(Provider< xxViewImpl> viewProvider) {       assert viewProvider != null;       this.viewProvider = viewProvider;   }   @Override   public xxPresenter get() {       return new xxPresenter(viewProvider.get());   }  public static Factory< XXPresenter> create(Provider< XXViewImplw> viewProvider) {       return new XXPresenter_Factory(viewProvider);   }        可以看到参数是一个Provider类型,范型参数是View层 ,通过构造方法对viewProvider进行实例化。成员参数没有直接用xxViewImpl 而通过Provider类型修饰是因为前者是一个依赖,而依赖提供者是XXModule,因此这个viewProvider也是由XXModule提供的       下面的get()函数内,也可以看到,在这里实例化了xxPresenter对象 通过new xxPresenter(依赖的xxViewImpl,只是是通过get()函数获取的)       最后通过create()函数,将含有一个参数viewProvider用来创建 XXPresenter_Factory类   接下来再来看一下,XXModule类对应的注入类 public final class XXModule_ProvideMainViewFactory implements Factory< xxViewImpl> {   private final XXModule module;   public XXModule_ProvideXXViewFactory(XXModule module) {       assert module != null;       this.module = module;   }     @Override   public xxViewImpl get() {       return Preconditions.checkNotNull(               module.provideXXView(), "Cannot return null from a [email  protected] @Provides method");   }     public static Factory< xxViewImpl> create(XXModule module) {       return new XXModule_ProvideXXViewFactory(module);   } }       在Module类中被@Provides修饰的方法都会对应的生成一个工厂类。这里是XXModule_ProvideXXViewFactory, 我们看到这个类里有一个get()方法,其中调用了XXModule里的provideXXView()方法来返回我们所需要的依赖xxViewImpl。还记得在xxPresenter_Factory里的get()方法中,实例化XXPresenter时候的参数viewProvider.get()吗?到这里我们就明白了,原来那个viewProvider就是生成的XXModule_ProvideXXViewFactory,然后调用了其get()方法,将我们需要的xxViewImpl注入到XXPresenter里。   思考:xxPresenter_Factory的创建是由create()完成的,但是这个create是在什么位置调用的? 答案显而易见肯定是在桥梁类Component 注入类中完成的。     示例伪代码:public final class DaggerXXComponent implements XXComponent {   private Provider< xxViewImpl> provideXXViewProvider;   private Provider< XXPresenter> XXPresenterProvider;   private MembersInjector< XXActivity> XXActivityMembersInjector;       private DaggerXXComponent(Builder builder) {       assert builder != null;       initialize(builder);   }   public static Builder builder() {       return new Builder();   }               在initialize()函数中,可以看到三个create()方法,每一个provider工厂都对应一个providerFactory.craete()实例,将providerXXViewProvider作为参数传递给XXPresenterProvider,后又又作为参数传递给Activity的注入类:XXActivityMembersInjector对象进行实例化。   @SuppressWarnings("unchecked")   private void initialize(final Builder builder) {       this.provideXXViewProvider = XXModule_ProvideXXViewFactory.create(builder.XXModule);       this.XXPresenterProvider = XXPresenter_Factory.create(provideXXViewProvider);       this.XXActivityMembersInjector = XXActivity_MembersInjector.create(XXPresenterProvider);   }       从伪代码中可以看出 ,定义的xxComponent会生成一个对应的DaggerXXComponent类,并且该类实现了XXComponent接口里的方法。   @Override   public void inject(XXActivity activity) {       XXActivityMembersInjector.injectMembers(activity); //将Activity注入到该类中   }   public static final class Builder {       private XXModule XXModule;       private Builder() {}       public XXComponent build() {           if (xxModule == null) {               throw new IllegalStateException(XXModule.class.getCanonicalName() + " must be set");           }           return new DaggerXXComponent(this);       }       public Builder XXModule(XXModule XXModule) {           this.XXModule = Preconditions.checkNotNull(XXModule);           return this;       }   } }      从伪代码中发现,Builder内部类就是用来创建module以及自身实例的,所以放在了DaggerXXComponent里进行初始化依赖,而真正让依赖关联起来的就是xxActivityMembersInjector对象。      public final class XXActivity_MembersInjector implements MembersInjector< XXActivity> {   private final Provider< XXPresenter> XXPresenterProvider;   public XXActivity_MembersInjector(Provider< XXPresenter> XXPresenterProvider) {       assert XXPresenterProvider != null;       this.XXPresenterProvider = XXPresenterProvider;   }   public static MembersInjector< XXActivity> create(           Provider< XXPresenter> XXPresenterProvider) {       return new XXActivity_MembersInjector(XXPresenterProvider);   }   @Override   public void injectMembers(XXActivity instance) {       if (instance == null) {           throw new NullPointerException("Cannot inject members into a null reference");       }       instance.XXPresenter = XXPresenterProvider.get();   }   public static void injectXXPresenter(           XXActivity instance, Provider< XXPresenter> XXPresenterProvider) {       instance.XXPresenter = XXPresenterProvider.get();   } }       从这里发现,将xxPresenterProvider中创建好的xxPresenter实例赋值给instance的成员xxPresenter。这样用@Inject标注的xxPresenter就得到了实例化了,进而在代码中进行实际使用。  小结:
  •   Module 并不是必须品,但是Component 是必不可少的
  •     编译后生成的Component实现类的名称必然是:Dagger+自定义Component接口名称
  •   在使用dagger2 时候,定义类或是方法名字的时候要遵守google的固定标准方便代码维护
  •   定义的Component 和Module结尾一样要以此结尾命名
  •   Module中@Provides 标注的方法要遵循规则以provide开头命名
  •   Component中 返回值为void且有参数的方法,参数是最重要的代表的是要注入的目标类,方法名一般使用inject
  •   Component 中返回值不为void 且无参数,返回值是最重要的代表的是暴露给子Component 使用的依赖 或是获取的子Component的类型
        本章部分内容摘自: https://www.jianshu.com/p/39d1df6c877d  https://juejin.im/entry/59e55646f265da43111f4548 感谢分享 respect   结语:       尽可能的达到高内聚低耦合的目标,正是呆哥兔追求的意义。   八、dagger2的扩展延伸-dagger.android 用于android的注入方式:       @Component( modules = {AndroidInjectionModule.class,AppModule.class})     public interface AppComponent {           void inject(App app);     }   @Subcomponent (modules = {MainActivityModule.class})     public interface MainActivityComponent extends AndroidInjector< MainActivity> {           void inject(MainActivity activity);                       @Subcomponent.Builder           public abstrace class Builder extends AndroidInjector.Builder< MainActivity> {} }   注意:
  •       在父Module中添加 @Module(subcomponents ={子Component})方式进行关联
  •     在这样的情况下,子Component中必须存在被@Subcomponent.Builder标注的抽象类或是接口,否则会报异常
    @Module     public class MainActivityModule{                 @Provides                 ActivityBean provideActivityBean(){                       return new ActivityBean():                 }     }    @Module (subcomponents = {MainActivityComponent.class});     public  abstract class AppModule{           @Provides           static AppBean provideAppBean(){                 return new AppBean():           }     @Binds       @IntoMap     @ActivityKey( MainActivity.class)     abstract AndroidInjector.Factory                                     < ? extends Activity> bindFactory(MainActivityComponent).inject(this);   在Activity中的实现:       public class App extends Application implements HasActivityInjector{           @Inject                 DispatchingAndroidInjector< Activity> activityInjector;           @Override                 public void onCreate(){                 DaggerAppComponent.create().inject(htis):           }           @Override                 public AndroidInjector< Activity> activityInjector(){                 return activityInjector;           }     }     public class MainActivity extends AppCompatActivity {                 @Inject                    AppBean appBean;                 @Inject                 ActivityBean activityBean;           @Override           protected void onCreate(Bundle saveInstanceState){                 AndroidInjection.inject(this);                 super.onCreate(saveInstanceState);                   ….             } }   dagger.android 小结       1、在AppComponent中将dagger2库里的AndroidInjectionModule注入到Applicaation中,并将Application实现响应的接口,并返回响应的方法;     2、子Component继承自AndroidInjector,内部BUilder使用抽象类并继承AndroidInjector.Builder;     3、父 Module 使用 @Module ( subcomponents = {} ) 的方式关联子 Component,并在父 Module 中编写返回值为 AndroidInjector.Factory、参数为子 Component.Builder 的抽象方法(如果有其他被 @Provides 标注的方法,应将方法改为 static,否则报错); 4、最后在 Acitivity 的 onCreate() 中第一行代码的位置使用 AndroidInjection 注入,如果是 Fragment 则是在 onAttach() 方法中,其他的请自行查阅。 5、dagger.android 库也提供了其他实现方式,诸如DaggerApplication、DaggerActivity、DaggerFragment、DaggerService、DaggerBroadcastReceiver 等实现类,有兴趣的小伙伴自己研究一下吧  

    推荐阅读