[Android] Dagger2 入门 2
来源:互联网 发布:银川网络机柜厂家 编辑:程序博客网 时间:2024/04/28 04:17
上一篇文章介绍了Dagger2的基本用法,这篇文章主要说一下Dagger2中@Scope和@Subcomponent这两个注解的用法和原理。@Singleton
上一篇文章中提到:如上面例子所示,如果要求D对象为单例,可以通过@Singleton注解来实现。首先我们需要在依赖图中声明对象是单例的:在我们看来,只是多加了一个注解而已,便实现了单例模式。要知道其原理,要从Dagger2生成的源码入手。
@Module public class DModule { @Provides @Singleton public D provideD() { return new D(); } } DComponent接口也需要声明:如此,当我们注入D对象时,可保证每次注入的是同一个D对象:@Singleton@Component(modules = DModule.class)public interface DComponent { D provideD();}
DComponent dComponent = DaggerDComponent.create();D d1 = dComponent.provideD(); D d2 = dComponent.provideD(); // d1 == d2
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
@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); }}
- 定义Component接口:
@Component(module=ABCModule.class)public interface ABCComponent { public A provideA(); public B provideB(); public C provideC(); void inject(Main main);}
- 依赖注入: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在项目路径下生成了如下文件:
注意,生成的文件在关联的类相同路径下。如DaggerABCComponent类生成在ABCComponent路径下。我们先来看看实际接触到的DaggerABCComponent类:[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)生成了文件结构图)
来看几个关键点:@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进行依赖注入。
这几个关键类的关系可用下图表示:
其中最最关键的是Factory和Provider。以B类为例,从依赖图中取出B对象,需要经过如下代码:+---------------------------------------+| DaggerABCComponent || || +----------+ create +-----------+------------+| | Factory +-----+-----> | Provider<A> || +----+-----+ | +----+------+------------+| ^ | | | || | | | +--v------+------------+| | +-----> | |Provider<B> || | ABCModule | | +--+------+------------+| | | | | || | | +----v------+------------+| +----+----+ +-----> | Provider<C> || | Builder | +-----------+------------+| +---------+ || || +--------------------+ +-----------+------------+| |Main_MembersInjector+--> | MembersInjector<Main> || +--------------------+ +-----------+------------+| |+---------------------------------------+
ABCModule_ProvideBFactory的源码如下所示:...this.provideBProvider = ABCModule_ProvideBFactory.create(builder.aBCModule, provideAProvider);...@Overridepublic B provideB() { return provideBProvider.get();}
Factory和Provider接口如下所示:@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); }}
从使用者的角度看,无需关心对象是如何生成的,只需调用provider的get方法即可获得对象。而且这时的对象应该是符合既定的规则并且初始化好可以马上用的。从ABCModule_ProvideBFactory(或者某个Provider)的角度看,在初始化方法里就明确了自己所需依赖的对象(这里是ProviderA)。在get方法的实现里,只需关心B对象的生成。当需要A对象时,直接从外部“注入”的providerA取出即可。再来看一看Main_MembersInjector的实现:public interface Factory<T> extends Provider<T> {}public interface Provider<T> { T get();}
@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
- [Android] Dagger2 入门 2
- [Android] Dagger2 入门 1
- Android开发Dagger2入门
- Android Dagger2简单入门
- Android:dagger2详解 2
- Dagger2入门
- dagger2入门
- Dagger2入门
- Dagger2入门
- Dagger2入门
- Dagger2 入门
- Dagger2入门
- 【Android】Dagger2从入门到再入门
- 【Android 进阶】Dagger2 系列:入门案例一
- Android Dagger2入门详解(一)
- Android Dagger2入门详解(二)
- Android Dagger2入门详解(三)
- Android Dagger2入门详解(四)
- 三极管的检测及其管脚的判别
- Handler的使用
- 占位
- 占位
- linq无法创建“匿名类型”类型的常量值;此上下文仅支持基元类型或枚举类型
- [Android] Dagger2 入门 2
- 水下文字
- 转的真不错
- 剑指Offer_40_数组中只出现一次的数字
- 滴滴美团58携程,那些发生在大并购谈判桌背后的故事
- 占位
- IDEA快捷键
- SurfacaView
- mendeley使用技巧