[Android] Dagger2 入门 2

上一篇文章介绍了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
    @Module
    public 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 {
    @Inject
    C 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);
...

@Override
public 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值