框架介绍
roboguice是google公司的一款依赖注入框架,基于guice。可以减少findviewbyid的使用和new的使用。
使用方法
在android studio中使用
在gradle中使用如下语句可以引入roboguice.
project.dependencies {
compile 'org.roboguice:roboguice:3.+'
provided 'org.roboguice:roboblender:3.+'
}
在activity中使用
activity必须继承RoboActivity。
public class MyActivity extends RoboActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
绑定view
- 绑定contentview:@ContentView(R.layout.main)。
- 绑定view:@injectView(R.id.textview) TextView textview;
绑定资源
@InjectResource(R.anim.my_animation) Animation myAnimation;
绑定服务
@Inject Vibrator vibrator;
@Inject NotificationManager notificationManager;
这里的服务不是android四大组件中的服务,而是指系统服务。系统服务是Android操作系统Java应用程序下层的,伴随操作系统启动而运行的系统后台服务程序(位于Android系统的FrameWork层)。
绑定pojo类
pojo类是简单的java bean类。
class Foo {
@Inject Bar bar;
}
class Foo{
Bar bar;
@inject Foo(Bar bar){
this.bar=bar;
}
}
单例模式
普通单例模式
@Singleton the whole app
class Foo {
}
这种单例在整个生命周期中有效,Foo类不会被垃圾回收器回收,除非整个应用结束。
Context中单例
@ContextSingleton context
class Foo {
}
在整个Context生命周期内为单例,当Context存活时,Foo类不会被垃圾回收器回收。
Fragment中单例
@FragmentSingleton
public class Bar {
}
在Fragment的整个生命周期中为单例,当fragment不被销毁时,Foo类不会被垃圾回收器回收。
绑定自己的类
类:
public interface IFoo {}
public class Foo implements IFoo {}
在activity中注入
public class MyActivity extends RoboActivity {
//How to tell RoboGuice to inject an instance of Foo ?
@Inject IFoo foo;
}
在AndroidManiFest.xml中注册
android:value="com.example.MyModule,com.example.MyModule2" />
创建module继承自AbstractModule
package com.example;public class MyModule extends AbstractModule {
//a default constructor is fine for a Modulepublic 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)); }
}
绑定intentExtra数据
@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); }
}
在Fragment中使用
必须继承RoboFragment
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); }
}
在onViewCreated方法中使用注入的view。
在service中和broadcast receiver中使用
必须继承RoboService
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();
}}
public class MyBroadcastReceiver extends BroadcastReceiver {@Inject ComputeFooModule computeFooModule;
protected void handleReceive(Context context, Intent intent) { //All injections are available from here : computeFooModule.setUp().computeFoo(); ...
}
}
绑定自定义View
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()); }
}
通过
RoboGuice.getInjector(getContext()).injectMembers(this);来绑定view。
在ContentProvider中注入
在module中使用
@Provides
@Named("example_authority_uri")
注释来绑定。
通过
@Inject
@Named("example_authority_uri")
来使用。
比如:
public class ContentProvidersModule extends AbstractModule {
@Override
protected void configure() {
}@Provides @Named("example_authority_uri") public Uri getExampleAuthorityUri() { return Uri.parse("content://com.example.data"); }
}
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; }
}
RoboGuice中的Event使用
RoboGuice中实现了自己的观察者模式,可以在Context中传递事件。(不能跨Actibity传递事件感觉比较鸡肋)
其中系统已经实现的事件有:
OnActivityResultEvent
OnConfigurationChangedEvent
OnContentChangedEvent
OnContentViewAvailableEvent
OnCreateEvent
OnDestroyEvent
OnNewIntentEvent
OnPauseEvent
OnRestartEvent
OnResumeEvent
OnStartEvent
-
OnStopEvent
通过在activity中使用如下方法可以监听这些事件:
public void doSomethingOnResume( @Observes OnResumeEvent onResume ) {
Ln.d("Called doSomethingOnResume in onResume");
}
使用@Observes这个注释来观察这个事件。
或者在activity中声明一个监听器来监听事件
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"); }
}
自定义事件
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 { ... }
总结
RoboGuice作为一款依赖注入框架可以提供多种注入,比如视图、pojo类、自定义类等。大量减少了findviewbyid和new的编写。
当一个类依赖于另一个类时,需要在类中创建一个类的实例。当使用了依赖注入后,所依赖的类的创建不在类中,而是在外部创建然后注入到类里面。
与ButterKnife和xutils3的区别
缺点
- ButterKnife和xutils3的注入支持绑定事件和在Adapter中使用,但是RoboGuice不可以,这是RoboGuice最大的缺点。
- Event只能在同一个Context中传递,感觉略鸡肋。
优点
- RoboGuice可以注入资源、动画和系统服务等,减少了代码量使代码更加简洁。
- 依赖类的初始化不用在类中完成,解耦。
- 可以通过@single、@contextsingle、@fragmentsingle来确定作用域。
- @provide提供了强大的绑定类型能力。
- 可以绑定IntentExtra中的数据