guice/roboguice框架学习

框架介绍

<p> roboguice是google公司的一款依赖注入框架,基于guice。可以减少findviewbyid的使用和new的使用。</p>

使用方法

在android studio中使用

<p>在gradle中使用如下语句可以引入roboguice.</p>
<pre> project.dependencies {
compile 'org.roboguice:roboguice:3.+'
provided 'org.roboguice:roboblender:3.+'
}</pre>

在activity中使用

activity必须继承RoboActivity。
<pre>
public class MyActivity extends RoboActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
</pre>

绑定view
  1. 绑定contentview:@ContentView(R.layout.main)。
  2. 绑定view:@injectView(R.id.textview) TextView textview;
绑定资源

<pre>@InjectResource(R.anim.my_animation) Animation myAnimation;</pre>

绑定服务

<pre> @Inject Vibrator vibrator;
@Inject NotificationManager notificationManager;</pre>

这里的服务不是android四大组件中的服务,而是指系统服务。系统服务是Android操作系统Java应用程序下层的,伴随操作系统启动而运行的系统后台服务程序(位于Android系统的FrameWork层)。

绑定pojo类

pojo类是简单的java bean类。
<pre>class Foo {
@Inject Bar bar;
}
class Foo{
Bar bar;
@inject Foo(Bar bar){
this.bar=bar;
}
}</pre>

单例模式
普通单例模式

<pre>
@Singleton the whole app
class Foo {
}</pre>

这种单例在整个生命周期中有效,Foo类不会被垃圾回收器回收,除非整个应用结束。

Context中单例

<pre>
@ContextSingleton context
class Foo {
}
</pre>

在整个Context生命周期内为单例,当Context存活时,Foo类不会被垃圾回收器回收。

Fragment中单例

<pre>
@FragmentSingleton
public class Bar {
}
</pre>

在Fragment的整个生命周期中为单例,当fragment不被销毁时,Foo类不会被垃圾回收器回收。

绑定自己的类

类:
<pre>
public interface IFoo {}
public class Foo implements IFoo {}
</pre>

在activity中注入
<pre>
public class MyActivity extends RoboActivity {
//How to tell RoboGuice to inject an instance of Foo ?
@Inject IFoo foo;
}
</pre>

在AndroidManiFest.xml中注册
<pre>
<application ...>
<meta-data android:name="roboguice.modules"
android:value="com.example.MyModule,com.example.MyModule2" />
</application>
</pre>

创建module继承自AbstractModule
<pre>
package com.example;

public class MyModule extends AbstractModule {
//a default constructor is fine for a Module

public void bind() {
    bind(IFoo.class).to(Foo.class);
}

}

public class MyModule2 extends AbstractModule {
//if your module requires a context, add a constructor that will be passed a context.
private Context context;

//with RoboGuice 3.0, the constructor for AbstractModule will use an `Application`, not a `Context`
public MyModule( Context context ) {
    this.context = context;
}

public void bind() {
    bind(IFoo.class).toInstance( new Foo(context));
}

}

</pre>

绑定intentExtra数据

<pre>
@ContentView(R.layout.activity_second)
public class SecondActivity extends RoboFragmentActivity {

@InjectExtra(value = "pull", optional = true)
String pull;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Gson gson = RoboGuice.getInjector(this).getInstance(Gson.class);
    String demoStr = gson.toJson(pull);
    Ln.d(demoStr);
}

}
</pre>

在Fragment中使用

必须继承RoboFragment
<pre>
public class MyFragment extends RoboFragment {
// Inject your view
@InjectView(R.id.text1) TextView nameTextView;

// Inflate your view as you normally would for any fragment...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.my_layout, container, false);
}

}
</pre>

在onViewCreated方法中使用注入的view。

在service中和broadcast receiver中使用

必须继承RoboService
<pre>
public class MyService extends RoboService {

@Inject ComputeFooModule computeFooModule;

public void onCreate() {
super.onCreate();
//All injections are available from here :
computeFooModule.setUp();
}

public int onStartCommand(Intent intent, int flags, int startId) {
computeFooModule.computeFoo();
return super.onStartCommand();
}

}
</pre>

<pre>
public class MyBroadcastReceiver extends BroadcastReceiver {

@Inject ComputeFooModule computeFooModule;

protected void handleReceive(Context context, Intent intent) {
    //All injections are available from here :
    computeFooModule.setUp().computeFoo();
    ...

}

}</pre>

绑定自定义View

<pre>
class MyView extends View {
@Inject Foo foo;
@InjectView(R.id.my_view) TextView myView;

public MyView(Context context) {
    inflate(context,R.layout.my_layout, this);
    RoboGuice.getInjector(getContext()).injectMembers(this);
    onFinishInflate();
}

public MyView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    inflate(context,R.layout.my_layout, this);
}

public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
    inflate(context,R.layout.my_layout, this);
}

@Override
public void onFinishInflate() {
    super.onFinishInflate();
    //All injections are available from here
    //in both cases of XML and programmatic creations (see below)
    myView.setText(foo.computeFoo());
}

}
</pre>

通过<pre>RoboGuice.getInjector(getContext()).injectMembers(this);</pre>来绑定view。

在ContentProvider中注入

在module中使用
<pre>
@Provides
@Named("example_authority_uri")</pre>
注释来绑定。
通过
<pre>
@Inject
@Named("example_authority_uri")
</pre>
来使用。
比如:
<pre>
public class ContentProvidersModule extends AbstractModule {
@Override
protected void configure() {
}

@Provides
@Named("example_authority_uri")
public Uri getExampleAuthorityUri() {
    return Uri.parse("content://com.example.data");
}

}
</pre>
<pre>
public class MyExampleContentProvider extends RoboContentProvider {

@Inject
@Named("example_authority_uri")
private Uri contentUri;

private UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

@Override
public boolean onCreate() {
    super.onCreate();
    uriMatcher.addURI(contentUri.getAuthority(), "foo/#", 0);
    return true;
}

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    switch (uriMatcher.match(uri)) {
        case 0:
            // Return results of your query
            return null;
        default:
            throw new IllegalStateException("could not resolve URI: " + uri);
    }

    return null;
}

@Override
public String getType(Uri uri) {
    return null;
}

@Override
public Uri insert(Uri uri, ContentValues values) {
    return null;
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
    return 0;
}

@Override
public int update(Uri uri, ContentValues contentValues, String selection, String[] selectionArgs) {
    return 0;
}

}
</pre>

RoboGuice中的Event使用

RoboGuice中实现了自己的观察者模式,可以在Context中传递事件。(不能跨Actibity传递事件感觉比较鸡肋)
其中系统已经实现的事件有:

  • OnActivityResultEvent

  • OnConfigurationChangedEvent

  • OnContentChangedEvent

  • OnContentViewAvailableEvent

  • OnCreateEvent

  • OnDestroyEvent

  • OnNewIntentEvent

  • OnPauseEvent

  • OnRestartEvent

  • OnResumeEvent

  • OnStartEvent

  • OnStopEvent
    通过在activity中使用如下方法可以监听这些事件:
    <pre>
    public void doSomethingOnResume( @Observes OnResumeEvent onResume ) {
    Ln.d("Called doSomethingOnResume in onResume");
    }
    </pre>
    使用@Observes这个注释来观察这个事件。
    或者在activity中声明一个监听器来监听事件
    <pre>
    public class MyActivity extends RoboActivity {
    // You must "register" your listener in the current context by injecting it.
    // Injection is commonly done here in the activity, but can also be done anywhere really.
    @Inject protected MyListener myListener;

    }

    class MyListener {

      // Any method with void return type and a single parameter with @Observes annotation
      // can be used as an event listener.  This one listens to onResume.    
      public void doSomethingOnResume( @Observes OnResumeEvent onResume ) {
          Ln.d("Called doSomethingOnResume in onResume");
      }
    

    }

</pre>

自定义事件

<pre>
public class MyOtherActivity extends RoboActivity {
// You'll need the EventManager if you want to trigger an event.
@Inject protected EventManager eventManager;

    @InjectView(R.id.buy_button) protected Button buyButton;

    protected void onCreate( Bundle savedInstanceState ) {
        super.onCreate(savedInstanceState);

        buyButton.setOnClickListener( new OnClickListener() {
            public void onClick() {
                // trigger the event
                eventManager.fire(new MyBuyEvent() );
            }
        })
    }

    // handle the buy event
    protected void handleBuy( @Observes MyBuyEvent buyEvent ) {
        Toast.makeToast(this, "You won't regret it!", Toast.LENGTH_LONG).show();
    }
}

// The event class can be anything you want
class MyBuyEvent {
    ...
}

</pre>

总结

RoboGuice作为一款依赖注入框架可以提供多种注入,比如视图、pojo类、自定义类等。大量减少了findviewbyid和new的编写。
当一个类依赖于另一个类时,需要在类中创建一个类的实例。当使用了依赖注入后,所依赖的类的创建不在类中,而是在外部创建然后注入到类里面。

与ButterKnife和xutils3的区别
缺点
  • ButterKnife和xutils3的注入支持绑定事件和在Adapter中使用,但是RoboGuice不可以,这是RoboGuice最大的缺点。
  • Event只能在同一个Context中传递,感觉略鸡肋。
优点
  • RoboGuice可以注入资源、动画和系统服务等,减少了代码量使代码更加简洁。
  • 依赖类的初始化不用在类中完成,解耦。
  • 可以通过@single、@contextsingle、@fragmentsingle来确定作用域。
  • @provide提供了强大的绑定类型能力。
  • 可以绑定IntentExtra中的数据
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,594评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,421评论 25 707
  • 从这段时间的时间开销记录中,收获如下: 1、对工具的用法更具逻辑性。开始系统的使用”爱今天“,同时对标签与目标的定...
    彭玄霏阅读 516评论 1 4
  • 告别了清明细雨,又迎来了春日暖阳。一个人坐在院子里晒晒太阳,脑子里思绪万千没有主线。 无聊之际一只蚂蚁进入...
    麦落阅读 325评论 2 2
  • 北国的秋,终于还是愈来愈远了。 幸而,今日得偿所愿。 丁酉九月,绿城西行百二十里,有竹林,见长寿山。山不以寿,以其...
    colo木叶阅读 179评论 0 0