[Android] Dagger2 入门 2

来源:互联网 发布:银川网络机柜厂家 编辑:程序博客网 时间:2024/04/28 04:17
上一篇文章介绍了Dagger2的基本用法,这篇文章主要说一下Dagger2中@Scope和@Subcomponent这两个注解的用法和原理。

@Singleton

上一篇文章中提到:
如上面例子所示,如果要求D对象为单例,可以通过@Singleton注解来实现。首先我们需要在依赖图中声明对象是单例的:
@Module public class DModule { @Provides @Singleton public D provideD() { return new D(); } } DComponent接口也需要声明:
@Singleton@Component(modules = DModule.class)public interface DComponent {    D provideD();}
如此,当我们注入D对象时,可保证每次注入的是同一个D对象:
DComponent dComponent = DaggerDComponent.create();D d1 = dComponent.provideD(); D d2 = dComponent.provideD(); // d1 == d2
在我们看来,只是多加了一个注解而已,便实现了单例模式。要知道其原理,要从Dagger2生成的源码入手。

Dagger2生成的源码

以如下例子为例:
  1. 定义类:
    public class A {    public A(){    }}public class B {    A a;    public B(A a) {        this.a = a;    }}public class C {    A a;    B b;    public C(A a, B b) {        this.a = a;        this.b = b;    }}
  2. 定义Module
    @Modulepublic class ABCModule {    @Provides    public A provideA() {        return new A();    }    @Provides    public B provideB(A a) {        return new B(a);    }    @Provides    public C provideC(A a, B b) {        return new C(a, b);    }}
  3. 定义Component接口:
    @Component(module=ABCModule.class)public interface ABCComponent {    public A provideA();    public B provideB();    public C provideC();    void inject(Main main);}
  4. 依赖注入:public class Main {
    @InjectC c;public Main() {    ABCComponent abcComponent = DaggerABCComponent            .builder()            .dComponent(dComponent)            .build();    A a = abcComponent.provideA();    B b = abcComponent.provideB();    abcComponent.inject(this);}
    }

编译工程,Dagger2在项目路径下生成了如下文件:

[dagger2]┣━[di]┃  ┣━[component]┃  ┃  ┗━DaggerABCComponent.java┃  ┗━[module]┃      ┣━ABCModule_ProvideAFactory.java┃      ┣━ABCModule_ProvideBFactory.java┃      ┗━ABCModule_ProvideCFactory.java┗━[model]    ┗━Main_MembersInjector.java// (利用[这个工具](https://gist.github.com/legendmohe/02908fefcd7f2c888084)生成了文件结构图)
注意,生成的文件在关联的类相同路径下。如DaggerABCComponent类生成在ABCComponent路径下。我们先来看看实际接触到的DaggerABCComponent类:
@Generated("dagger.internal.codegen.ComponentProcessor")public final class DaggerABCComponent implements ABCComponent {  private Provider<A> provideAProvider;  private Provider<B> provideBProvider;  private Provider<C> provideCProvider;  private MembersInjector<Main> mainMembersInjector;  private DaggerABCComponent(Builder builder) {      assert builder != null;    initialize(builder);  }  public static Builder builder() {      return new Builder();  }  public static ABCComponent create() {      return builder().build();  }  private void initialize(final Builder builder) {      this.provideAProvider = ABCModule_ProvideAFactory.create(builder.aBCModule);    this.provideBProvider = ABCModule_ProvideBFactory.create(builder.aBCModule, provideAProvider);    this.provideCProvider = ABCModule_ProvideCFactory.create(builder.aBCModule, provideAProvider, provideBProvider);    this.mainMembersInjector = Main_MembersInjector.create(provideCProvider);  }  @Override  public A provideA() {      return provideAProvider.get();  }  @Override  public B provideB() {      return provideBProvider.get();  }  @Override  public C provideC() {      return provideCProvider.get();  }  @Override  public void inject(Main main) {      mainMembersInjector.injectMembers(main);  }  public static final class Builder {    private ABCModule aBCModule;    private Builder() {      }    public ABCComponent build() {        if (aBCModule == null) {        this.aBCModule = new ABCModule();      }      return new DaggerABCComponent(this);    }    public Builder aBCModule(ABCModule aBCModule) {        if (aBCModule == null) {        throw new NullPointerException("aBCModule");      }      this.aBCModule = aBCModule;      return this;    }  }}
来看几个关键点:
  1. DaggerABCComponent继承于ABCComponent。所以我们可以直接调用ABCComponent的方法。

  2. DaggerABCComponent需要Builder来进行初始化。Builder的作用是提供对象的module。

  3. 对象通过Provider从依赖图中取出。Provider由Factory生成时会有类似依赖注入的操作。

  4. 通过MembersInjector进行依赖注入。

这几个关键类的关系可用下图表示:

+---------------------------------------+|         DaggerABCComponent            ||                                       ||  +----------+  create     +-----------+------------+|  |  Factory +-----+-----> |  Provider<A>           ||  +----+-----+     |       +----+------+------------+|       ^           |       |    |      ||       |           |       | +--v------+------------+|       |           +-----> | |Provider<B>           ||       | ABCModule |       | +--+------+------------+|       |           |       |    |      ||       |           |       +----v------+------------+|  +----+----+      +-----> |  Provider<C>           ||  | Builder |              +-----------+------------+|  +---------+                          ||                                       || +--------------------+    +-----------+------------+| |Main_MembersInjector+--> |  MembersInjector<Main> || +--------------------+    +-----------+------------+|                                       |+---------------------------------------+
其中最最关键的是Factory和Provider。以B类为例,从依赖图中取出B对象,需要经过如下代码:
...this.provideBProvider = ABCModule_ProvideBFactory.create(builder.aBCModule, provideAProvider);...@Overridepublic B provideB() {      return provideBProvider.get();}
ABCModule_ProvideBFactory的源码如下所示:
@Generated("dagger.internal.codegen.ComponentProcessor")public final class ABCModule_ProvideBFactory implements Factory<B> {  private final ABCModule module;  private final Provider<A> aProvider;  public ABCModule_ProvideBFactory(ABCModule module, Provider<A> aProvider) { // 根据之前的依赖关系,注入ProviderA      assert module != null;    this.module = module;    assert aProvider != null;    this.aProvider = aProvider;  }  @Override  public B get() {      B provided = module.provideB(aProvider.get()); // 从ProviderA中取出A对象,再生成B对象    if (provided == null) {      throw new NullPointerException("Cannot return null from a non-@Nullable @Provides method");    }    return provided;  }  public static Factory<B> create(ABCModule module, Provider<A> aProvider) {      return new ABCModule_ProvideBFactory(module, aProvider);  }}
Factory和Provider接口如下所示:
public interface Factory<T> extends Provider<T> {}public interface Provider<T> {    T get();}
从使用者的角度看,无需关心对象是如何生成的,只需调用provider的get方法即可获得对象。而且这时的对象应该是符合既定的规则并且初始化好可以马上用的。从ABCModule_ProvideBFactory(或者某个Provider)的角度看,在初始化方法里就明确了自己所需依赖的对象(这里是ProviderA)。在get方法的实现里,只需关心B对象的生成。当需要A对象时,直接从外部“注入”的providerA取出即可。再来看一看Main_MembersInjector的实现:
@Generated("dagger.internal.codegen.ComponentProcessor")public final class Main_MembersInjector implements MembersInjector<Main> {  private final Provider<C> cProvider;  public Main_MembersInjector(Provider<C> cProvider) {      assert cProvider != null;    this.cProvider = cProvider;  }  @Override  public void injectMembers(Main instance) {      if (instance == null) {      throw new NullPointerException("Cannot inject members into a null reference");    }    instance.c = cProvider.get();  }  public static MembersInjector<Main> create(Provider<C> cProvider) {        return new Main_MembersInjector(cProvider);  }}

@Scope

@Component和Subcomponent

我是怎么用Dagger2的

总结



查看原文:http://legendmohe.net/2016/08/22/android-dagger2-%e5%85%a5%e9%97%a8-2/
0 0
原创粉丝点击