Dagger 2学习与探索(四)

上一期介绍了Dagger是如何应对多个同类型变量的,这一期主要介绍,在对原对象不做任何修改的情况下如何将其注入。

主体代码

现在将ClassA的所有标注全都去掉:

public class ClassA {

  private int a;
  private int b;

  public ClassA(int a, int b) {
    this.a = a;
    this.b = b;
  }

  public int getA() {
    return a;
  }

  public int getB() {
    return b;
  }
}

好了,那么现在Dagger要从哪里知道ClassA的构造函数以及参数呢?
答案是在Module里。现在Dagger自己无法查到ClassA的带@Inject标注的构造器了,于是转而要Module @Provides一个出来,具体如下:

@Module
public class ModuleA {
  private int a;
  private int b;

  public ModuleA(int a, int b) {
    this.a = a;
    this.b = b;
  }

  @Provides
  @Named("a")
  int provideIntA() {
    return a;
  }

  @Provides
  @Named("b")
  int provideIntB() {
    return b;
  }

  @Provides
  ClassA provideClassA(@Named("a") int a, @Named("b") int b) {
    return new ClassA(a, b);
  }
}

是不是和原来的ClassA的构造器很像?更神奇的一点是,Dagger会自动搜索所需参数,然后在这里找@Provides同类型参数的函数,同样多个同类型的参数可以用@Named来解决。
当然也可以不必这么麻烦,可以在构造ModuleA的时候new一个ClassA出来,到时候返回去。可见Dagger也是很有自由发挥空间的,只要把握几个要点就可以了。
比如说Dagger生成的DaggerComponent其实可以不急于inject,而是需要的时候再inject。常见的就是在App初始化的时候生成一堆之后可能需要的DaggerComponent,然后等哪个地方需要就获取然后再注入。
MainActivityClassAComponent并没有什么变化。

生成代码

生成代码没有太多变化,除了ClassA原来的构造器Dagger不知道了,现在用ModuleA_ProvideClassAFactory来代替:

public final class ModuleA_ProvideClassAFactory implements Factory<ClassA> {
  private final ModuleA module;

  private final Provider<Integer> aProvider;

  private final Provider<Integer> bProvider;

  public ModuleA_ProvideClassAFactory(
      ModuleA module, Provider<Integer> aProvider, Provider<Integer> bProvider) {
    assert module != null;
    this.module = module;
    assert aProvider != null;
    this.aProvider = aProvider;
    assert bProvider != null;
    this.bProvider = bProvider;
  }

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

  public static Factory<ClassA> create(
      ModuleA module, Provider<Integer> aProvider, Provider<Integer> bProvider) {
    return new ModuleA_ProvideClassAFactory(module, aProvider, bProvider);
  }

  /** Proxies {@link ModuleA#provideClassA(int, int)}. */
  public static ClassA proxyProvideClassA(ModuleA instance, int a, int b) {
    return instance.provideClassA(a, b);
  }
}

生成的代码确实是“一个模子”里出来的。
这里体现出封装的好处了:在无法直接调用构造器的情况下,使用Provider接口封装之后其余代码几乎没有什么区别。

到目前为止,我们看到的只是很简单的依赖关系,那么交叉依赖又如何?例如ClassB需要ClassA与另一个整数a,而ClassA又依赖于a?Dagger是提供了很多方法来解决的,我们拭目以待吧。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容