Dagger2 探索记2——四大基本组件(二)

       书接上文,先回顾以下前一章写的内容。

       内容大概就是在Activity中用@Inject标记一个注入的类,然后在这个类的构造函数上也打个@Inject标记,然后使用@Component来连接两边,完成对象的创建和注入。整体流程朴实无华,且枯燥。

       到这里可能就有花生发现了西瓜!

       如果要注入的是第三方库呢?我不可能去把封装好的第三方库打开,然后给它的构造函数打个@Inject!

       那么我们就要引入四大基本组件的后两个组件:@Module和@Provide。

       这两个是配套使用的,我直接在上一章的代码上改:

       先新建一个FirstModule类:

@Module
public class FirstModule {

    @Provides
    Tools provideTools(){
        return new Tools();
    }
}

       @Provide标记的方法就是提供依赖的方法,一般方法名写成provide+类名。

       约定俗成,约定俗成!理解万岁,李姐万岁!

       然后在FirstComponent里面加上依赖

@Component(modules = FirstModule.class)//绑定Module
public interface FirstComponent {

    void inject(FirstActivity activity);

}

       为什么上一章我强烈不建议使用create()代替builder().build()呢?

       原因就在这里,如果添加了Module就不能使用create()了,必须改回去。

       将Activity中的注入语句也要更改:

DaggerFirstComponent.builder()
                .firstModule(new FirstModule())//添加Module
                .build()
                .inject(this);

      添加的代码如果标红了,就证明你没有编译,生成的DaggerFirstComponent中没有这个firstModule()方法。

      上面代码很简单,把原来应该标记在class里构造函数的标记,移到了@Module里,@Module就像个包装盒,这个我们后面再讲。

      先跑一下,看AS又给我们生成了什么有趣的东西。

      老规矩,按逻辑来,先看DaggerFirstComponent.java

 1 public final class DaggerFirstComponent implements FirstComponent {
 2   private Provider<Tools> provideToolsProvider;
 3 
 4   private MembersInjector<FirstActivity> firstActivityMembersInjector;
 5 
 6   private DaggerFirstComponent(Builder builder) {
 7     assert builder != null;
 8     initialize(builder);
 9   }
10 
11   public static Builder builder() {
12     return new Builder();
13   }
14 
15   public static FirstComponent create() {
16     return builder().build();
17   }
18 
19   @SuppressWarnings("unchecked")
20   private void initialize(final Builder builder) {
21 
22     this.provideToolsProvider = FirstModule_ProvideToolsFactory.create(builder.firstModule);
23 
24     this.firstActivityMembersInjector = FirstActivity_MembersInjector.create(provideToolsProvider);
25   }
26 
27   @Override
28   public void inject(FirstActivity activity) {
29     firstActivityMembersInjector.injectMembers(activity);
30   }
31 
32   public static final class Builder {
33     private FirstModule firstModule;
34 
35     private Builder() {}
36 
37     public FirstComponent build() {
38       if (firstModule == null) {
39         this.firstModule = new FirstModule();
40       }
41       return new DaggerFirstComponent(this);
42     }
43 
44     public Builder firstModule(FirstModule firstModule) {
45       this.firstModule = Preconditions.checkNotNull(firstModule);
46       return this;
47     }
48   }
49 }

      很长,先不看,待会儿有需要再回来翻。

      先是builder(),建造者模式,没啥变化。但是Builder类中多了个方法,也就是前面提到的firstModule():

    public Builder firstModule(FirstModule firstModule) {
      this.firstModule = Preconditions.checkNotNull(firstModule);
      return this;
    }

      其实也没干啥,就在Builder中存了个Module的实例,我们Module中就一个provide方法,返回一个new Tools()。

      这里有个checkNotNull,很好理解,就不多说了。

      然后build(),又对DaggerFirstComponent进行初始化。(我为什么要说又?)

      看起来是老调重弹,但我们又确确实实在里面找到了不一样的东西,看看initialize方法中的代码

this.provideToolsProvider = FirstModule_ProvideToolsFactory.create(builder.firstModule);

this.firstActivityMembersInjector = FirstActivity_MembersInjector.create(provideToolsProvider);

      这个工厂类和之前的不一样了,FirstModule_ProvideToolsFactory。

      看到个很熟悉的单词:Provide。没错,这个新的工厂类就是@Module和@Provide组合形成的新工厂类。

      看看这个新工厂类的代码:

public final class FirstModule_ProvideToolsFactory implements Factory<Tools> {
  private final FirstModule module;

  public FirstModule_ProvideToolsFactory(FirstModule module) {
    assert module != null;
    this.module = module;
  }

  @Override
  public Tools get() {
    return Preconditions.checkNotNull(
        module.provideTools(), "Cannot return null from a non-@Nullable @Provides method");
  }

  public static Factory<Tools> create(FirstModule module) {
    return new FirstModule_ProvideToolsFactory(module);
  }
}

       大失所望,代码还没名字长。

       create()方法传进去一个module实例,然后把实例保存下来。需要get()时,就调用module.providTools()。

       这个工厂类和之前的工厂类唯一区别就是create()方法多传了个module实例,用来调用provide方法。

       绕了一圈,和前一章的方法又重合了。

       相信认真看第一章的小伙伴都知道后面会发生啥。

       等我会,我去上一章复制点文字来。

       ......

       5、调用DaggerFirstComponent方法将工厂类的实例和Activity的实例都交给MemberInjecter

       6、MemberInjecter组装完成,依赖成功注入。

      是不是很眼熟?其实也没多难。

      看完这四大组件的介绍,相信你对Dagger2已经有了基本的认识。

      我们再来形象化的描述一下依赖注入的过程。

      要给Activity进行依赖注入,最重要的就是要new一个指定对象赋值给Activity中用@Inject标记的那个声明。

      其实就跟淘宝买东西一样,你在Activity中的声明就是下单,这里需要一个对象,请给我快递送过来。(那么问题来了,你的对象呢?)

      对象哪里来呢?

      工厂类。

      至于是@Inject工厂还是@Provide工厂?都可以,会做蛋炒饭就行。

      唯一不同的是,@provide工厂发出来的快递有个快递箱@Module装着。

      我看的很多博客喜欢在@Module中给定个成员变量FirstActivity,美其名曰给快递盒上写上地址。

      可不可以呢?可以。

      有没有必要呢?看情况,个人观点,不调用,就没必要。

      因为@Component这个快递员知道地址,你写不写,不重要。如果是要寄两家的快递,岂不是还要写两个地址?

      但这里要注意个坑,前面我们都把@Module和@Component绑定了,一个@Component可以绑定多个@Module,但是多个@Module中提供的方法不能相同(其实可以,需要点小技巧)。但这还不是我要说的坑。

      如果@Inject和@Provide同时存在,总有个优先级...吧?(我没有连读!)

      华生们,我前面删Tools类里的@Inject了吗?      谁优先级高不言而喻。

      流程是这样的,@Component会先去找绑定的@Module和@provide,没有才去找@Inject。

      如果绑定的@Module中有@Provide()方法,但是你注入时没有调用firstModule()这个方法,会报错。

 

      基本源代码就分析到这,相比大家对Dagger2也有了基本了解,下面我就来讲讲稍微复杂点的用法。

 

 

 

 

 

 

 

      还是下章吧........

posted @ 2019-09-19 00:38  缘溪行  阅读(246)  评论(0编辑  收藏  举报