Dragger代码实现
转自:http://www.apkbus.com/blog-705730-60436.html
在工程中引入Dagger
如果想使用Dagger的话,需要添加两个函数库:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.squareup.dagger:dagger:1.2.+'
provided 'com.squareup.dagger:dagger-compiler:1.2.+'
}
第一个是Dagger函数库,第二个是Dagger编译器函数库,它会创建注入依赖所需的类。通过创建预编译的类可以避免大部分的反射操作。由于我们只需要Dagger编译器函数库来编译工程,在应用中不会使用到它,因此我们把它标记为provided,这样在最终的apk中就不会包含这个函数库了。
创建第一个module
Modules是使用Dagger经常碰到的概念,所以你需要习惯它们。Modules是提供依赖注入时所需对象实例的类,它们通过@Module注解来修饰类。还有其他一些额外参数可能需要配置,但我们会在使用到的时候再进行介绍。
创建一个名为AppModule的类,假设用于提供Application Context。为Application Context提供简单的访问入口通常是有趣的。我创建继承自Application的类App,并添加到AndroidManifest文件中。
@Module(
injects = {
App.class
}
)
public class AppModule {
private App app;
public AppModule(App app) {
this.app = app;
}
@Provides @Singleton public Context provideApplicationContext() {
return app;
}
}
上面涉及到哪些新知识呢?
- @Module:把这个类标识为Dagger module。 injects:标识module将要注入这个类的任何依赖。我们需要明确指定将直接注入到对象图中的那些类,这将很快会讲到。
- @Providers:标识函数作为注入提供者,函数名并不重要,它只依赖于所提供的类类型。
- @Singleton:如果标识为Singleton,那这个函数会一直返回相同的对象实例,这比常规的单例好很多。否则,每次注入类型都会得到一个新的实例。在这个例子中,由于我们没有创建新实例,而是返回已经存在的实例,因此即使不把函数标识为Singleton,每次调用还是会返回相同的实例的,但这样能够更好地说明提供者到底做了什么。Application实例是唯一的。
为什么常规的单例是不好的
单例可能是一个工程能够具有的最危险的依赖了。首先,由于我们没有创建实例,因此很难知道要在什么地方使用它,因此具有“隐藏依赖”。另外,我们没有办法通过mock来测试它,或者以另外的模块替换它,因此代码变得难以维护,测试和进化。被注入的单例,相反,具有单例的优势(唯一的实例),同时,由于我们可以在任何时候创建新的实例,因此很容易mock或者通过子类化或者使其实现一个公有接口来使用另一个代码片段替换它。
我们将在一个新的名为domain的包里面创建另外一个module。在每个架构层拥有至少一个module是很有用的。这个module将提供一个统计管理器,在app启动时通过显示一个Toast来抛出一个事件。在实际的工程中,这个管理器可能调用任何统计服务例如Google Analytics。
@Module(
complete = false,
library = true
)
public class DomainModule {
@Provides @Singleton public AnalyticsManager provideAnalyticsManager(Application app){
return new AnalyticsManager(app);
}
}
通过把这个module指明为未完成,表示这个module的某些依赖需要另外一个module来提供。也就是AppModule里面的Application。当我们从一个依赖注入请求这个AnalyticsManager时,dagger将会使用这个函数,并会检测到它需要另外一个依赖:Application,这会通过向对象图发起请求来获得。我们同时需要把module指明为library,因为dagger编译器会检测到AnalyticsMananger没有被它自身或者它的注入类所使用。对于AppModule来说,DomainModule就是一个库模块。
我们将指定AppModule会包含DomainModule,因此返回AppModule类,修改代码如下:
@Module(
injects = {
App.class
},
includes = {
DomainModule.class
}
)
public class AppModule {
...
}
includes属性正是用来实现这个目的的。
创建对象图
对象图是所有依赖存在的地方。对象图包含被创建的实例,并能够把这些实例注入到相应的对象中。
在前面的例子中(AnalyticsManager)我们看到了经典的依赖注入,注入是通过构造函数参数传递的。但在Android中有的类(Application,Activity)我们对构造函数没有控制权,因此我们需要另外一种方式来注入依赖。
ObjectGraph创建和直接注入的组合方式在App类中可以看到。主对象图在Application类中创建并被注入以获得依赖。
public class App extends Application {
private ObjectGraph objectGraph;
@Inject AnalyticsManager analyticsManager;
@Override public void onCreate() {
super.onCreate();
objectGraph = ObjectGraph.create(getModules().toArray());
objectGraph.inject(this);
analyticsManager.registerAppEnter();
}
private List<Object> getModules() {
return Arrays.<Object>asList(new AppModule(this));
}
}
我们通过@Inject注解来指明谁是依赖,这些依赖项必须是public或者default范围的,以便dagger可以给它们赋值。我们创建了一个modules数组(我们只有一个module,DomainModule是包含在AppModule里面的),并通过它来创建一个ObjectGraph实例。然后,我们手动注入App实例,这样之后,依赖就被注入了,因此可以直接调用AnalyticsManager的函数了。
结论
现在你掌握了Dagger的基础用法。ObjectGraph和Modules是有效的使用Dagger必须掌握的最有意思的组件。还有其他更多的工具例如懒注入或者provider注入,在Dagger网页上面有介绍,但在你熟练掌握本文所介绍的知识之前,我不建议你深入研究它们。
git示例源码:https://github.com/ppamorim/Dragger
Dragger代码实现的更多相关文章
- android ListView和GridView拖拽移位实现代码
关于ListView拖拽移动位置,想必大家并不陌生,比较不错的软件都用到如此功能了.如:搜狐,网易,百度等,但是相比来说还是百度的用户体验较好,不偏心了,下面看几个示例: 首先 ...
- 日期格式代码出现两次的错误 ORA-01810
错误的原因是使用了两次MM . 一.Oracle中使用to_date()时格式化日期需要注意格式码 如:select to_date('2005-01-01 11:11:21','yyyy-MM-dd ...
- 可爱的豆子——使用Beans思想让Python代码更易维护
title: 可爱的豆子--使用Beans思想让Python代码更易维护 toc: false comments: true date: 2016-06-19 21:43:33 tags: [Pyth ...
- iOS代码规范(OC和Swift)
下面说下iOS的代码规范问题,如果大家觉得还不错,可以直接用到项目中,有不同意见 可以在下面讨论下. 相信很多人工作中最烦的就是代码不规范,命名不规范,曾经见过一个VC里有3个按钮被命名为button ...
- Jquery的点击事件,三句代码完成全选事件
先来看一下Js和Jquery的点击事件 举两个简单的例子 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&q ...
- redux-amrc:用更少的代码发起异步 action
很多人说 Redux 代码多,开发效率低.其实 Redux 是可以灵活使用以及拓展的,经过充分定制的 Redux 其实写不了几行代码.今天先介绍一个很好用的 Redux 拓展-- redux-amrc ...
- 编写高质量代码:改善Java程序的151个建议(第5章:数组和集合___建议75~78)
建议75:集合中的元素必须做到compareTo和equals同步 实现了Comparable接口的元素就可以排序,compareTo方法是Comparable接口要求必须实现的,它与equals方法 ...
- 使用 .NET WinForm 开发所见即所得的 IDE 开发环境,实现不写代码直接生成应用程序
直接切入正题,这是我09年到11年左右业余时间编写的项目,最初的想法很简单,做一个能拖拖拽拽就直接生成应用程序的工具,不用写代码,把能想到的业务操作全部封装起来,通过配置的方式把这些业务操作组织起来运 ...
- jsp前端实现分页代码
前端需要订一page类包装,其参数为 private Integer pageSize=10; //每页记录条数=10 private Integer totalCount; //总记录条数 priv ...
随机推荐
- Thinkphp Ajax传地址
在使用文本编辑器时,如果加入图片,涉及到图片的src,需要用到Ajax传地址到处理页面. 在使用Ajax的过程中,如果要通过JSON传递路径值到处理页面,会出现传值不正确. 解决方法就是在传值之前将路 ...
- fedora20 播放aiv视频
环境:fedora20 64位 下载个教程是avi的格式,用FEDORA自带的视频播放提示少插件,搜索又没有. 到网上搜索后,参考下面的方式添加软件仓库后,再打开视频播放顺利装好插件.但视频画件一闪 ...
- 使用Ajax.ActionLink时,点击对应的按钮会重新加载一个页面,而不是在当前页面的指定模块加载
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- IOS学习:常用第三方库(GDataXMLNode:xml解析库)
IOS学习:常用第三方库(GDataXMLNode:xml解析库) 解析 XML 通常有两种方式,DOM 和 SAX: DOM解析XML时,读入整个XML文档并构建一个驻留内存的树结构(节点树),通过 ...
- 令用EclipseJ2EE创建的Dynamic Web project目录结构与用MyEclipse创建的Web project一样
Eclipse for EE 版本, 创建 Dynamic Web Project 会有俩个工程. 其中一个 是你创建的工程, 另外一个 是Servers 工程(其实也就是tomcat 的一个配置) ...
- kibo.js 处理键盘事件的Javascript工具库
这个也是做在线编辑用到的 选中文字快捷键.提高编辑效率 https://github.com/marquete/kibo 用法很简单 Examples var k = new Kibo(); Sing ...
- 用C#实现网络爬虫(二)
上一篇<用C#实现网络爬虫(一)>我们实现了网络通信的部分,接下来继续讨论爬虫的实现 3. 保存页面文件 这一部分可简单可复杂,如果只要简单地把HTML代码全部保存下来的话,直接存文件就行 ...
- cf C. Inna and Dima
http://codeforces.com/contest/374/problem/C 记忆化搜索,题意:求按照要求可以记过名字多少次,如果次数为无穷大,输出Poor Inna!,如果不经过一次输出P ...
- XML SAX解析
SAX是一种占用内存少且解析速度快的解析器,它采用的是事件驱动,它不需要解析完整个文档,而是按照内容顺序,看文档某个部分是否符合xml语法,如果符合就触发相应的事件.所谓的事件就是些回调方法( cal ...
- Windows消息编程(写的不错,有前因后果)
本文主要包括以下内容: 1.简单理解Windows的消息2.通过一个简单的Win32程序理解Windows消息3.通过几个Win32程序实例进一步深入理解Windows消息4.队列消息和非队列消息5. ...