经过前两篇的介绍,我们了解了如何使用RoboGuice方便的为我们注入需要的对象,这篇将着重说明原理。

一.Guice与RoboGuice

Guise是Google开发的一个轻量级的依赖注入框架,主要针对Java使用的。

RoboGuice是基于Guice库开发,目的为Android提供一套简单易用的依赖注入框架。

上两篇中所提到的POJO注入,说白了就是对象注入,大部分方法都是Guice框架中的。RoboGuice主要在视图注入及Android个性化的注入上下功夫。

二.RoboGuice注入对象

就算没用过RoboGuice,但是大家也都听过,RoboGuice是通过反射来实现注入的。

为了了解实现的原理,我们先看下RoboActivity的代码。

其中eventManager初始化方式使用的就是之前提过的RoboGuice.getInjector(),其内部提供了各种事件的注册,反注册,分发等等功能。

public class RoboActivity extends Activity implements RoboContext {
protected EventManager eventManager;
protected HashMap<Key<?>,Object> scopedObjects = new HashMap<Key<?>, Object>(); @Inject ContentViewListener ignored; // BUG find a better place to put this
private Stopwatch stopwatch; @Override
protected void onCreate(Bundle savedInstanceState) {
stopwatch = new Stopwatch();
final RoboInjector injector = RoboGuice.getInjector(this);
stopwatch.resetAndLog("RoboActivity creation of injector");
eventManager = injector.getInstance(EventManager.class);
stopwatch.resetAndLog("RoboActivity creation of eventmanager");
injector.injectMembersWithoutViews(this);
stopwatch.resetAndLog("RoboActivity inject members without views");
super.onCreate(savedInstanceState);
stopwatch.resetAndLog("RoboActivity super onCreate");
eventManager.fire(new OnCreateEvent<Activity>(this,savedInstanceState));
stopwatch.resetAndLog("RoboActivity fire event");
}
}

其次注意到被注入的ContentViewListener,这就是为了实现在Activity上的ContentView的注解,这里的方法是

@ContextSingleton
public class ContentViewListener {
@Inject protected Activity activity; public void optionallySetContentView( @Observes OnCreateEvent<?> ignored ) {
Class<?> c = activity.getClass();
while( c != Context.class ) {
final ContentView annotation = c.getAnnotation(ContentView.class);
if( annotation!=null ) {
activity.setContentView(annotation.value());
return;
}
c = c.getSuperclass();
}
}
}

这里观察的是OnCreate的事件,事件的分发代码在OnCreate方法中,实现了setContentView的方法。

onCreate方法简化后如下。可以发现inject对象的时机是在super的onCreate之前的,

@Override
protected void onCreate(Bundle savedInstanceState) {
final RoboInjector injector = RoboGuice.getInjector(this);
eventManager = injector.getInstance(EventManager.class);
injector.injectMembersWithoutViews(this);
super.onCreate(savedInstanceState);
eventManager.fire(new OnCreateEvent<Activity>(this,savedInstanceState));
}

RoboInjector其实是RoboGuice内部的一个Guice Injector,大部分注入工作交给了Guice。

反射注入这一块就不深入讨论了,下面贴出了Guice的部分代码。

private static void computeInjectableMembers(TypeLiteral<?> type, boolean statics, Errors errors, InjectionPoint.InjectableMembers injectableMembers, InjectionPoint.OverrideIndex overrideIndex, HierarchyTraversalFilter filter) {
Class rawType = type.getRawType();
if(isWorthScanning(filter, rawType)) {
Class parentRawType = rawType.getSuperclass();
if(isWorthScanning(filter, parentRawType)) {
computeInjectableMembers(type.getSupertype(parentRawType), statics, errors, injectableMembers, overrideIndex, filter);
overrideIndex.position = InjectionPoint.Position.MIDDLE;
} else {
overrideIndex.position = InjectionPoint.Position.TOP;
} Set allFields = filter.getAllFields(Inject.class.getName(), rawType);
if(allFields != null) {
Iterator allMethods = allFields.iterator(); while(allMethods.hasNext()) {
Field i$ = (Field)allMethods.next();
if(Modifier.isStatic(i$.getModifiers()) == statics) {
Annotation method = getAtInject(i$);
if(method != null) {
InjectionPoint.InjectableField atInject = new InjectionPoint.InjectableField(type, i$, method);
if(atInject.jsr330 && Modifier.isFinal(i$.getModifiers())) {
errors.cannotInjectFinalField(i$);
} injectableMembers.add(atInject);
}
}
}
} Set allMethods1 = filter.getAllMethods(Inject.class.getName(), rawType);
if(allMethods1 != null) {
Iterator i$1 = allMethods1.iterator(); while(true) {
while(true) {
while(true) {
Method method1;
do {
if(!i$1.hasNext()) {
return;
} method1 = (Method)i$1.next();
} while(!isEligibleForInjection(method1, statics)); Annotation atInject1 = getAtInject(method1);
if(atInject1 != null) {
InjectionPoint.InjectableMethod removed2 = new InjectionPoint.InjectableMethod(type, method1, atInject1);
if(!checkForMisplacedBindingAnnotations(method1, errors) && isValidMethod(removed2, errors)) {
if(statics) {
injectableMembers.add(removed2);
} else {
overrideIndex.removeIfOverriddenBy(method1, true, removed2);
overrideIndex.add(removed2);
}
} else {
boolean removed1 = overrideIndex.removeIfOverriddenBy(method1, false, removed2);
if(removed1) {
logger.log(Level.WARNING, "Method: {0} is not a valid injectable method (because it either has misplaced binding annotations or specifies type parameters) but is overriding a method that is valid. Because it is not valid, the method will not be injected. To fix this, make the method a valid injectable method.", method1);
}
}
} else {
boolean removed = overrideIndex.removeIfOverriddenBy(method1, false, (InjectionPoint.InjectableMethod)null);
if(removed) {
logger.log(Level.WARNING, "Method: {0} is not annotated with @Inject but is overriding a method that is annotated with @javax.inject.Inject. Because it is not annotated with @Inject, the method will not be injected. To fix this, annotate the method with @Inject.", method1);
}
}
}
}
}
}
}
}

三.总结

这三篇过来,依赖注入给我们带来了什么?

解耦。

当我们在一个对象中,不需要关心它所依赖的成员如何初始化,只关心用来使用或获取属性,依赖注入为我们实现了解耦。

再就是RoboGuice的贴心,将Android基本组件考虑在内,为我们实现了很多注入,减少了我们调用系统服务或组件的代码,再就是RoboGuice考虑到了Android生命周期的特殊问题,将注入的成员对象生命周期保持与Context生命周期一致。

再说说反射,尽管RoboGuice强调,使用roboblender会优化很大一部分注解性能,但是反射对于移动端设备参差不齐的配置,还是让人有一点点担心,如果项目足够大,且使用了大量的注解及注入,那么性能一定是有影响的。

最后,RoboGuice确实是一个值得使用的框架,使用简单、上手较快、能实现模块解耦。光凭这几点优点便足以打动人心。

RoboGuice 3.0 (三)总结篇的更多相关文章

  1. RoboGuice 3.0 (一)入坑篇

    RoboGuice是什么? 一个Android上的依赖注入框架. 依赖注入是什么? 从字面理解,这个框架做了两件事情,第一是去除依赖,第二是注入依赖.简单理解就是,将对象的初始化委托给一个容器控制器, ...

  2. Aurora 8B/10B、PCIe 2.0、SRIO 2.0三种协议比较

    在高性能雷达信号处理机研制中,高速串行总线正逐步取代并行总线.业界广泛使用的Xilinx公司Virtex-6系列FPGA支持多种高速串行通信协议,本文针对其中较为常用的Aurora 8B/10B和PC ...

  3. Delphi 泛型(三十篇)

    Delphi 泛型(三十篇)http://www.cnblogs.com/jxgxy/category/216671.html

  4. RoboGuice 3.0 (二)进阶篇

    上篇介绍了RoboGuice的接入及基本使用,其中涉及到了一个@Singleton和@ContextSingleton的注解,这些都是作用域的注解,这篇我们先说明有关作用域的问题. 一.作用域 Sco ...

  5. JavaScript 面向对象(三) —— 高级篇

    JavaScript 面向对象(一) —— 基础篇 JavaScript 面向对象(二) —— 案例篇 一.json方式的面向对象 首先要知道,js中出现的东西都能够放到json中.关于json数据格 ...

  6. C#的变迁史 - C# 4.0 之多线程篇

    在.NET 4.0中,并行计算与多线程得到了一定程度的加强,这主要体现在并行对象Parallel,多线程Task,与PLinq.这里对这些相关的特性一起总结一下. 使用Thread方式的线程无疑是比较 ...

  7. 读懂IL代码就这么简单(三)完结篇

    一 前言 写了两篇关于IL指令相关的文章,分别把值类型与引用类型在 堆与栈上的操作区别详细的写了一遍 这第三篇也是最后一篇,之所以到第三篇就结束了,是因为以我现在的层次,能理解到的都写完了,而且个人认 ...

  8. ios -- 教你如何轻松学习Swift语法(三) 完结篇

    前言:swift语法基础篇(二)来了,想学习swift的朋友可以拿去参考哦,有兴趣可以相互探讨,共同学习哦.      一.自动引用计数   1.自动引用计数工作机制      1.1 swift和o ...

  9. Android UI开发第三十三篇——Navigation Drawer For Android API 7

    Creating a Navigation Drawer中使用的Navigation Drawer的android:minSdkVersion="14",现在Android API ...

随机推荐

  1. 【原创】开源Math.NET基础数学类库使用(10)C#进行基本数据统计

                   本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新  开源Math.NET基础数学类库使用总目录:[目录]开源Math.NET基础数学类库使用总目录 前言 ...

  2. javascript中异步和闭包产生的困惑

    这里我不打算大谈特谈什么是异步,什么是闭包,这些内容在博客园都已经写的够多的了,但是这些内容出现的多,并不代表所有初学者都已经撑握了,所以我还是打算,用一个比较常见的示例来分析一下,或许能让对这个问题 ...

  3. C语言 第三章 基础编程测试与练习

    1.屏幕上输出:This is a C program 2.输入两个整数,求两个数的和,如下所示:请输入第1个数:5请输入第2个数:3 3加5的和是8 3.完成华氏温度与摄氏温度间的转换,如下所示:请 ...

  4. 【Java心得总结二】浅谈Java中的异常

    作为一个面向对象编程的程序员对于 下面的一句一定非常熟悉: try { // 代码块 } catch(Exception e) { // 异常处理 } finally { // 清理工作 } 就是面向 ...

  5. 高版本->低版本迁移,低版本客户端连接高版本数据库EXP导出报错EXP-00008,ORA-01455,EXP-00000

    生产环境: 源数据库:RHEL + Oracle 11.2.0.3 目标数据库:HP-UX + Oracle 10.2.0.4   需求:迁移部分表  11.2.0.3-->10.2.0.4,若 ...

  6. Eclipse与Android源码中ProGuard工具的使用

    由于工作需要,这两天和同事在研究android下面的ProGuard工具的使用,通过查看android官网对该工具的介绍以及网络上其它相关资料,再加上自己的亲手实践,算是有了一个基本了解.下面将自己的 ...

  7. Web App 向上滑动动态加载数据 2015-06-11 09:36 20人阅读 评论(0) 收藏

    好久没有写博客了 - - ,个人原因 个人原因..  宣传一下...自己的.NET群:252713569 欢迎各位大神加入 嗯..最近在公司开发微信平台的东西..需要做一个WebAPP(PS:其实就是 ...

  8. [Java 基础]数据类型

    基本类型和引用类型 Java中的数据类型有两类: l  基本类型(又叫内置数据类型,或理解为值类型) l  引用类型 基本类型和引用类型的区别 1.  从概念方面来说 基本类型:变量名指向具体的数值 ...

  9. [Web API] Web API 2 深入系列(3) 激活HttpController

    目录 HttpController 创建HttpController IAssembliesResolver IHttpControllerTypeResolver HttpControllerTyp ...

  10. Alg-4:算法可视化tiny库的实现

    好吧,准备好好实践一下<算法>这本书的内容的,有点讨厌的是这本书是以Java作为示例语言的(好吧,我承认我有语言偏见,Java就是臭).其中有一个Std库,其中涉及到简化输入输出.随机数生 ...