RoboGuice 解析

背景:

网上各路资料都是浅层次的使用说明,即使是作为供他人使用的接口说明也是不合格的,所以还是得看看源码看官方文档。

Guice产生的源头

通常我们的一个Service 依赖多个其他的模块A,B,C, D,在Service里初始化这些A,B,C,D呢?大家都知道,搞UT的时候最麻烦最恶心的地方就是要考虑如何去Mock掉这些依赖,所以这样当然不是很好的方式。
那么通过setter来将它们设置进来呢?你会看到在实例化Service前有一大坨的对依赖的初始化代码。而且这些过程可能比较容易出错,比如你写的库给别人使用,其中的某个服务有较多的依赖,那么即使你写的很好的doc,而别人在使用的时候,会痛苦,最严重的是会出错。

那么Guice的作用就是 将依赖的处理也给默默的做了,那么在实例化服务的时候将会非常的清爽。
下面是SomeServices服务,其有两个依赖Depends2,Depends1

public class SomeServices {
    Depends2 depends2;
    @Inject
    Depends1 depends1;

    @Inject
    public SomeServices( Depends2 depends2) {
        this.depends2 = depends2;

    }

    public void start() {
        depends2.start();
        depends1.start();
    }
}

实例化SomeServices时候,只有简单的一行。

SomeServices someServices = Guice.createInjector(new SomeServicesModule()).getInstance(SomeServices.class);

Bindings

借助注解@Inject就能够将依赖给解决掉?这背后是如何实现的呢?
通过注解@Inject我们只知道依赖模块的类类型,也许他还是抽象类,离真正的解决依赖还有一段距离,那么就是通过Binding把这个差距给“连接”起来。

它在哪里实现

创建一个继承自AbstractModule的子类,然后实现configure方法。
Guice使用EDSL语言来使得创建bindings更简单可读性更好,
比如 bind ….to..
见:https://github.com/google/guice/wiki/Bindings
那么可以理解Bindings (实质就是对configure方法的实现过程)就是生成相应Injecter的一个配置。

那么RoboGuice又是?

RoboGuice 是Guice的扩展,增加了Android的支持。
从头说起,Guice跟Android平台无关,如果我们想使用一个fragment,他里面也是有很多依赖,依赖外界资源,依赖其他服务,依赖,依赖View组件,这堆依赖初始化也挺费事,直接用guice可以!但是你需要自己写Bindings, 比如@Inject Button btn;
那么RoboGuice就是帮你将Android平台下的Bindings给写好了。这就是他存在的意义。

继承RoboFragment?

那为什么没有见Guice.createInjector.getInstance之流?而是继承个RoboFragment?那么进入到RoboFragment中看看就明白了,在onCreate中

final RoboInjector injector = RoboGuice.getInjector(this);
injector.injectMembersWithoutViews(this);

RoboGuice 解析_第1张图片

getInjector 根据上下文环境获取适合的Injector,(获取方式暂时不关注它了)
然后调用injector的injectMembersWithoutViews方法,该方法主要就是注入非View的Java对象。

在onViewCreated中

RoboGuice.getInjector(getActionBarActivity()).injectViewMembers(this);

注:
所有对View的插入实现都在ViewMembersInjector中。

几个常用注解

注解名 意义
@InjectView(R.id.name)
@InjectResource(R.drawable.icon)
@Inject
@Singleton 我们想要使用单例模式(Singleton Pattern)来获取对象,即 One Instance in the application,你可以在实现类上使用 Singleton 注释去标记。
@ProvidedBy(AddProvider.class) 可以直接在接口声明处使用 ProvidedBy 注释来指定该接口的 Provider 类型
@ImplementedBy(SimpleAdd.class) 如果 Add 接口有多个实现类,但是我们希望 SimpleAdd 是 Add 的默认实现类
@InjectExtra (“Extra1” ) String extra1 ??

几个常用Bindings写法

类型 意义
binder.bind(Add.class).to(SimpleAdd.class)
bind(CityController.class).in(Singleton.class) 没有指明目标实现类,那么要求类CityController应该由@ImplementedBy或@ProvidedBy标注过(也就是间接的定义了目标实现类类型)
toProvider(new CategoryProvider()) 指出目标实现类的Provider
annotatedWith(Names.named(“deal”)) 在该接口声明的地方是否有注解Names(“deal”),一般当接口有多个实现类的时候,通过注解Names来标明最终是用哪个实现类实例化

指明目标实现类的方法

一.在configure方法中通过bind().to(Target.class);
二.创建实现Provider接口的类,并在configure方法中通过bind().toProvider(new TargetProvider());
三.在AbstractModule的子类中,编写方法,返回相应类型,并用注解@Provides标注该方法,和方法二类似。
四.在接口定义上以@ImplementedBy(SimpleAdd.class)或 @ProvidedBy(AddProvider.class)标注

参考链接:

Guice guide

Google Guice 系列教程 - 基础实践

Introduction to Google Guice

RoboGuice guide

你可能感兴趣的:(RoboGuice 解析)