接上一篇文章介绍了Dagger2的初步使用,相信刚接触的人会觉得很奇怪,怎么会有很多自己没有定义的代码出现,为什么Component的创建方式是那样的。为了搞清楚这些东西,我们需要查看一下Dagger2 生成的源代码。Dagger2 是一个DI框架,通过学习生成的代码也可以更好的理解Dagger2是如何做依赖注入的。

  将上一篇文章中的工程在SublimeText中打开,结构如下图:

  可以看到AppComponent 生成了 DaggerAppComponent,Dagger2的生成规则中,我们自定义的Component生成之后会加上前缀“Dagger”。此外Module中的每个@Provides 方法都会生成一个Factory 类,命名规则也是很规律的。这里Dagger一共为我们生成了6个类:DaggerAppComponent / AppModule_ProvideApplicationFactory /ReposListActivity_MembersInjector / GithubApiModule_ProvideRetrofitFactory / GithubApiModule_ProvideOkHttpClientFactory / GithubApiModule_ProvideGitHubServiceFactory。接下来我们看看这些类具体是什么样的。

  首先来看一下DaggerAppComponent:

@Generated("dagger.internal.codegen.ComponentProcessor")
public final class DaggerAppComponent implements AppComponent {
private Provider<Application> provideApplicationProvider;
private Provider<OkHttpClient> provideOkHttpClientProvider;
private Provider<Retrofit> provideRetrofitProvider;
private Provider<GithubApiService> provideGitHubServiceProvider;
private MembersInjector<ReposListActivity> reposListActivityMembersInjector; private DaggerAppComponent(Builder builder) {
assert builder != null;
initialize(builder);
} public static Builder builder() {
return new Builder();
} private void initialize(final Builder builder) {
this.provideApplicationProvider = AppModule_ProvideApplicationFactory.create(builder.appModule);
this.provideOkHttpClientProvider = GithubApiModule_ProvideOkHttpClientFactory.create(builder.githubApiModule);
this.provideRetrofitProvider = GithubApiModule_ProvideRetrofitFactory.create(builder.githubApiModule, provideApplicationProvider, provideOkHttpClientProvider);
this.provideGitHubServiceProvider = GithubApiModule_ProvideGitHubServiceFactory.create(builder.githubApiModule, provideRetrofitProvider);
this.reposListActivityMembersInjector = ReposListActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), provideGitHubServiceProvider);
} @Override
public void inject(ReposListActivity activity) {
reposListActivityMembersInjector.injectMembers(activity);
} public static final class Builder {
private AppModule appModule;
private GithubApiModule githubApiModule; private Builder() {
} public AppComponent build() {
if (appModule == null) {
throw new IllegalStateException("appModule must be set");
}
if (githubApiModule == null) {
this.githubApiModule = new GithubApiModule();
}
return new DaggerAppComponent(this);
} public Builder appModule(AppModule appModule) {
if (appModule == null) {
throw new NullPointerException("appModule");
}
this.appModule = appModule;
return this;
} public Builder githubApiModule(GithubApiModule githubApiModule) {
if (githubApiModule == null) {
throw new NullPointerException("githubApiModule");
}
this.githubApiModule = githubApiModule;
return this;
}
}
}

  我们在Application中实例化AppComponent的时候是这样的:

appComponent = DaggerAppComponent.builder()
.githubApiModule(new GithubApiModule())
.appModule(new AppModule(this))
.build();

  第一次见的时候肯定觉得一团雾水,为什么要这样写呢? 通过上面DaggerAppcomponent代码可以看出,使用了建造者模式。我们回顾一下AppComponent是怎么样的:

@Component(modules = { AppModule.class, GithubApiModule.class})
public interface AppComponent {
// inject what
void inject(ReposListActivity activity);
}

  @component 后面modules包含了两个类,在生成的DaggerAppComponent 中的内部类 Builder中,AppModule.class 和 GithubApiModule.class 成为了其成员,并且提供了set方法。在Application中实例化DaggerAppComponent的过程中其实就是调用了其set方法来设置依赖。此外在DaggerAppComponent各个@Provides 注解的方法返回类型都是其一个成员变量,并在Initialize()方法中创建。此外还有一个MembersInjector成员,DaggerAppComponent也要负责创建它。

@Generated("dagger.internal.codegen.ComponentProcessor")
public final class ReposListActivity_MembersInjector implements MembersInjector<ReposListActivity> {
private final MembersInjector<BaseActivity> supertypeInjector;
private final Provider<GithubApiService> githubApiServiceProvider; public ReposListActivity_MembersInjector(MembersInjector<BaseActivity> supertypeInjector, Provider<GithubApiService> githubApiServiceProvider) {
assert supertypeInjector != null;
this.supertypeInjector = supertypeInjector;
assert githubApiServiceProvider != null;
this.githubApiServiceProvider = githubApiServiceProvider;
} @Override
public void injectMembers(ReposListActivity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
supertypeInjector.injectMembers(instance);
instance.githubApiService = githubApiServiceProvider.get();
} public static MembersInjector<ReposListActivity> create(MembersInjector<BaseActivity> supertypeInjector, Provider<GithubApiService> githubApiServiceProvider) {
return new ReposListActivity_MembersInjector(supertypeInjector, githubApiServiceProvider);
}
}

  ReposListActivity_MembersInjector 中通过 injectMembers 方法获取到 ReposListActivity 的实例(对应的就是 ReposListActivityComponent中的inject),然后进行赋值。从这种赋值的方式来看被@Inject注解的注入对象不能是private的。在看赋值是通过 githubAPiServiceProvider.get() 方法获取的,githubApiServiceProvider是一个工厂类,我们来看看这个工厂类是怎么样的:

@Generated("dagger.internal.codegen.ComponentProcessor")
public final class GithubApiModule_ProvideGitHubServiceFactory implements Factory<GithubApiService> {
private final GithubApiModule module;
private final Provider<Retrofit> retrofitProvider; public GithubApiModule_ProvideGitHubServiceFactory(GithubApiModule module, Provider<Retrofit> retrofitProvider) {
assert module != null;
this.module = module;
assert retrofitProvider != null;
this.retrofitProvider = retrofitProvider;
}。 @Override
public GithubApiService get() {
GithubApiService provided = module.provideGitHubService(retrofitProvider.get());
if (provided == null) {
throw new NullPointerException("Cannot return null from a non-@Nullable @Provides method");
}
return provided;
} public static Factory<GithubApiService> create(GithubApiModule module, Provider<Retrofit> retrofitProvider) {
return new GithubApiModule_ProvideGitHubServiceFactory(module, retrofitProvider);
}
}

  GithubApiModule_ProvideGitHubServiceFactory 类中有两个成员,一个是提供(@Provides)GithubService 所在的 module 类,一个是创建GithubService方法所需参数的retrofitProvider(从这里可以看出Dagger2需要创建retrofitProvider的工厂)。然后通过 module.provdeGitHubService()方法来创建 GithubApiService实例,这样最终穿件了在ReposListActivity中注入的依赖实例。

  Dagger2 入门有点绕,也没找到什么系统性的资料,但是可以通过查看框架自动生成的类来加深理解,方便大家使用。使用到dependencies和SubComponent注解的时候生成的代码就比较多了,本来也想捋捋的,但是原理和上面的都是一样的,大家自己去看吧。

Dagger2 生成代码学习的更多相关文章

  1. (转)MyBatis框架的学习(七)——MyBatis逆向工程自动生成代码

    http://blog.csdn.net/yerenyuan_pku/article/details/71909325 什么是逆向工程 MyBatis的一个主要的特点就是需要程序员自己编写sql,那么 ...

  2. springboot学习随笔(四):Springboot整合mybatis(含generator自动生成代码)

    这章我们将通过springboot整合mybatis来操作数据库 以下内容分为两部分,一部分主要介绍generator自动生成代码,生成model.dao层接口.dao接口对应的sql配置文件 第一部 ...

  3. 【MyBatis学习15】MyBatis的逆向工程生成代码

    1. 什么是逆向工程 mybatis的一个主要的特点就是需要程序员自己编写sql,那么如果表太多的话,难免会很麻烦,所以mybatis官方提供了一个逆向工程,可以针对单表自动生成mybatis执行所需 ...

  4. 学习使用Lombok生成代码

    一.介绍 Lombok官网:https://projectlombok.org/ Lombok的功能简单一点说,就是可以帮我们生成一些代码,这些代码并不是在源码(source code)体现出来的,而 ...

  5. 前端学习笔记系列一:7 在vscode中根据vue等模板生成代码

    目标:希望每次新建.vue文件后,VSCODE能够根据配置,自动生成我们想要的内容. 方法:打开VSCODE编辑器,依次选择“文件 -> 首选项 -> 用户代码片段”,此时,会弹出一个搜索 ...

  6. Android注解使用之通过annotationProcessor注解生成代码实现自己的ButterKnife框架

    前言: Annotation注解在Android的开发中的使用越来越普遍,例如EventBus.ButterKnife.Dagger2等,之前使用注解的时候需要利用反射机制势必影响到运行效率及性能,直 ...

  7. mybatis Generator生成代码及使用方式

    本文原创,转载请注明:http://www.cnblogs.com/fengzheng/p/5889312.html 为什么要有mybatis mybatis 是一个 Java 的 ORM 框架,OR ...

  8. x01.CodeBuilder: 生成代码框架

    根据 Assembly 生成代码框架. 这是学习 AvalonEdit 的一个副产品.学习时,照着源代码新建文件夹,新建文件,添加方法与属性,虽然只是个框架,也要花费大量时间.为什么不让它自动生成呢? ...

  9. 使用 Velocity 模板引擎快速生成代码(zhuan)

    http://www.ibm.com/developerworks/cn/java/j-lo-velocity1/ ****************************************** ...

随机推荐

  1. Linux环境下中文字体乱码处理办法

    项目中包含了一项生成JPG图片的功能,该功能需要使用JAVA的Graphics2D动态生成图片中的文字,原来在Windows平台中没有发现问题,但是迁移至Linux平台后发现生成的中文变成了乱码. 百 ...

  2. 编码符_new

    begin#6BE3803ED5339EBA1028EF9FC2BBD85F196391DFC603EAE8B10BA25D0B69029667A9BD2D914CE59A26EF5ECF370D5C ...

  3. Linux下PHP安装oci8扩展

    PHP通常搭配Mysql使用,但有时候也会连接到Oracle数据库.安装PHP的oci8扩张之前,需要先安装Oracle Instant Client( basic 或 basic lite 版就行了 ...

  4. Percona Server 5.6.13-61.0 首个 GA 版本发布

    Percona Server 5.6 的首个 GA 版本发布了,版本号是 5.6.13-61.0 ,该版本基于 MySQL 5.6.13 改进内容包括: New Features: Percona S ...

  5. NoSQL:从关系型数据库到非关系型数据库

    关系型数据库 所谓关系型数据库,,就是指采用了关系模型来组织数据的数据库. 什么是关系模型,简单说,关系模型就是二维表格模型,而一个关系型数据库就是由二维表及其之间的联系所组成的一个数据组织. 关系模 ...

  6. 补充 作业八:团队项目——Alpha阶段项目总结 补充

    游戏界面: 单一.无背景图片 加入了背景 游戏结束: 无变化 无变化 游戏记录 无 加入数据库:有数据记录! 游戏初始化: 无 加入多种模式 此次任务后的总结: 经过上一次的答辩,以及认真观看了其他组 ...

  7. 团队项目——站立会议DAY7

    第七次站立会议记录: 参会人员:张靖颜,钟灵毓秀,何玥,赵莹,王梓萱 项目进展: 1.张靖颜:对功能模块代码进行近一步的审查和辅助,并对出错处进行修改和完善. 2.钟灵毓秀:对代码近一步的修改,将各个 ...

  8. 基于Winform、WPF等的客户端文件下载

    有时候,我们用C#写一些客户端应用程序需要从服务器下载一些资源,如图片.dll.配置文件等.下面就来说一下,在Winform及WPF中如何下载文件. 我们的资源大多放在自己的网站上,或者从其他网站下载 ...

  9. Android自定义View的构造函数

    自定义View是Android中一个常见的需求,每个自定义的View都需要实现三个基本的构造函数,而这三个构造函数又有两种常见的写法. 第一种 每个构造函数分别调用基类的构造函数,再调用一个公共的初始 ...

  10. CSS3 动画一瞥

    伴随HTML5而来的CSS3让前端大湿们可以用简单的CSS样式即可写出动画效果来,而在这之前,一提到动画我们可能会想到JavaScript,Flash,Java插件等.如果是用JavaScript那倒 ...