Dagger2 探索记3——两大进阶组件(二)

      经过了十来天的努力看代码写需求,成功的忘记了之前的博客写到哪了......

      先接着上章所说的,讲一下全局单例的源代码。

      代码如下

public final class DaggerSecondComponent implements SecondComponent {
  private Provider<Coffee> provideCoffeeProvider;

  private Provider<Global> globalProvider;

  private Provider<Tools> provideToolsProvider;

  private MembersInjector<SecondActivity> secondActivityMembersInjector;

  private MembersInjector<ThridActivity> thridActivityMembersInjector;

  private DaggerSecondComponent(Builder builder) {
    assert builder != null;
    initialize(builder);
  }

  public static Builder builder() {
    return new Builder();
  }

  @SuppressWarnings("unchecked")
  private void initialize(final Builder builder) {

    this.provideCoffeeProvider = SecondModule_ProvideCoffeeFactory.create(builder.secondModule);

    this.globalProvider =
        new Factory<Global>() {
          private final GlobalComponent globalComponent = builder.globalComponent;

          @Override
          public Global get() {
            return Preconditions.checkNotNull(
                globalComponent.global(),
                "Cannot return null from a non-@Nullable component method");
          }
        };

    this.provideToolsProvider = SecondModule_ProvideToolsFactory.create(builder.secondModule);

    this.secondActivityMembersInjector =
        SecondActivity_MembersInjector.create(
            provideCoffeeProvider, globalProvider, provideToolsProvider);

    this.thridActivityMembersInjector =
        ThridActivity_MembersInjector.create(provideCoffeeProvider, globalProvider);
  }

  @Override
  public void inject(SecondActivity activity) {
    secondActivityMembersInjector.injectMembers(activity);
  }

  @Override
  public void inject(ThridActivity activity) {
    thridActivityMembersInjector.injectMembers(activity);
  }

  public static final class Builder {
    private SecondModule secondModule;

    private GlobalComponent globalComponent;

    private Builder() {}

    public SecondComponent build() {
      if (secondModule == null) {
        this.secondModule = new SecondModule();
      }
      if (globalComponent == null) {
        throw new IllegalStateException(GlobalComponent.class.getCanonicalName() + " must be set");
      }
      return new DaggerSecondComponent(this);
    }

    public Builder secondModule(SecondModule secondModule) {
      this.secondModule = Preconditions.checkNotNull(secondModule);
      return this;
    }

    public Builder globalComponent(GlobalComponent globalComponent) {
      this.globalComponent = Preconditions.checkNotNull(globalComponent);
      return this;
    }
  }
}

       代码量有点让人头秃。。。。。。

       不过我们能按照注入时的代码顺序捋一下:

DaggerSecondComponent.builder()
                .globalComponent(new MyApplication().get())
                .secondModule(new SecondModule())//添加Module
                .build()
                .inject(this);

        比起之前的注入代码,我们多写了个globalcomponent,所以我们的Builder类中也就多了一个方法,其实和之前的注入也差不多,只不过相当于写了两个Module。

        但是到了initialize中就不一样了,我们可以看见个特立独行的方法:

this.globalProvider =
        new Factory<Global>() {
          private final GlobalComponent globalComponent = builder.globalComponent;

          @Override
          public Global get() {
            return Preconditions.checkNotNull(
                globalComponent.global(),
                "Cannot return null from a non-@Nullable component method");
          }
        };

         在这个方法中,给globalProvide赋值时,直接new了一个工厂类。工厂类中private一个final的GlobalComponent,也就是我们之前传入.globalComponent(new MyApplication().get())传入的Component。并重写了Global的get()方法,返回globalComponent.global()。

        回顾一下,这个方法在哪:

@Singleton
@Component(modules = GlobalModule.class)
public interface GlobalComponent {

    Global global();

}

       之前我们传入Component就是为了通过实例好的Component来调用其中的构造函数。

       一切都串起来了。

       为什么会有全局单例?

       因为不同Activity依赖注入时调用的Component是同一个,Component里面的方法还是@Singleton局部单例模式。所以注入的依赖也是同一个。

       好好品一下这个问题。

       让你的头发休息一下,然后接着看后面的。

       

       后面接着一个比较简单的进阶组件:@Qualifier

       和前面讲到的@Scope一样,也需要实现后在调用,默认实现有@Named。看看源码:

@Qualifier
@Documented
@Retention(RUNTIME)
public @interface Named {

    /** The name. */
    String value() default "";
}

       之前我们讲过Module中不能有相同返回类型的函数,但是如果我们有需要注入同一个类却要用不同的构造函数注入呢?

       就要用到函数命名了。两边标记就行,一边是Module中:

    @Named("null")
    @Provides
    Coffee provideCoffee(){
        return new Coffee();
    }

    @Named("lanshan")
    @Provides
    Coffee provideCoffee1(){
        return new Coffee("蓝山");
    }

         另一边就是Activity中:

    @Inject
    @Named("lanshan")
    Coffee coffee1;
    @Inject
    @Named("null")
    Coffee coffee2;

          如果自定义也很简单,和前面的一样,举两个栗子:

@Qualifier
@Documented
@Retention(RUNTIME)
public @interface MyNamed1 {
}
@Qualifier
@Documented
@Retention(RUNTIME)
public @interface MyNamed2 {
}

           因为没有写方法体,那就得一个函数实例化一个@Qualifier,远不如直接用@Named来的简单。

    @Inject
    @MyNamed1
    Coffee coffee1;
    @Inject
    @MyNamed2
    Coffee coffee2;

          这个我就不多讲了,相信大家都能看的一目了然。

          

          到此Dagger2的学习可以告一段落。剩下的疑难点需要在使用中慢慢发掘。

 

 

 

 

 

 

 

 

 

 

 

         (实际上我是过了五个月才发现还有篇草稿,忘了怎么往下写,直接结尾吧!)

 

posted @ 2020-02-18 11:28  缘溪行  阅读(161)  评论(0编辑  收藏  举报