框架介绍
<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
- 绑定contentview:@ContentView(R.layout.main)。
- 绑定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中的数据