您的位置:首页 > 移动开发 > Android开发

[Android] Dagger2 入门 2

2016-08-22 10:15 211 查看
上一篇文章介绍了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生成的源码

以如下例子为例:

定义类:

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;
}
}


定义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);
}
}


定义Component接口:

@Component(module=ABCModule.class)
public interface ABCComponent {
public A provideA();

public B provideB();

public C provideC();

void inject(Main main);
}


依赖注入:

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;
}
}
}


来看几个关键点:

DaggerABCComponent继承于ABCComponent。所以我们可以直接调用ABCComponent的方法。

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

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

通过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 M
4000
embersInjector<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/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: