框架介紹
<p> roboguice是google公司的一款依賴注入框架令境,基于guice孽亲。可以減少findviewbyid的使用和new的使用展父。</p>
使用方法
在android studio中使用
<p>在gradle中使用如下語(yǔ)句可以引入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>
綁定服務(wù)
<pre> @Inject Vibrator vibrator;
@Inject NotificationManager notificationManager;</pre>
這里的服務(wù)不是android四大組件中的服務(wù)栖茉,而是指系統(tǒng)服務(wù)篮绿。系統(tǒng)服務(wù)是Android操作系統(tǒng)Java應(yīng)用程序下層的,伴隨操作系統(tǒng)啟動(dòng)而運(yùn)行的系統(tǒng)后臺(tái)服務(wù)程序(位于Android系統(tǒng)的FrameWork層)吕漂。
綁定pojo類
pojo類是簡(jiǎn)單的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>
這種單例在整個(gè)生命周期中有效,F(xiàn)oo類不會(huì)被垃圾回收器回收惶凝,除非整個(gè)應(yīng)用結(jié)束吼虎。
Context中單例
<pre>
@ContextSingleton context
class Foo {
}
</pre>
在整個(gè)Context生命周期內(nèi)為單例,當(dāng)Context存活時(shí)苍鲜,F(xiàn)oo類不會(huì)被垃圾回收器回收思灰。
Fragment中單例
<pre>
@FragmentSingleton
public class Bar {
}
</pre>
在Fragment的整個(gè)生命周期中為單例,當(dāng)fragment不被銷毀時(shí)混滔,F(xiàn)oo類不會(huì)被垃圾回收器回收洒疚。
綁定自己的類
類:
<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中注冊(cè)
<pre>
<application ...>
<meta-data android:name="roboguice.modules"
android:value="com.example.MyModule,com.example.MyModule2" />
</application>
</pre>
創(chuàng)建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數(shù)據(jù)
<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>
通過(guò)<pre>RoboGuice.getInjector(getContext()).injectMembers(this);</pre>來(lái)綁定view坯屿。
在ContentProvider中注入
在module中使用
<pre>
@Provides
@Named("example_authority_uri")</pre>
注釋來(lái)綁定油湖。
通過(guò)
<pre>
@Inject
@Named("example_authority_uri")
</pre>
來(lái)使用。
比如:
<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中實(shí)現(xiàn)了自己的觀察者模式领跛,可以在Context中傳遞事件乏德。(不能跨Actibity傳遞事件感覺(jué)比較雞肋)
其中系統(tǒng)已經(jīng)實(shí)現(xiàn)的事件有:
OnActivityResultEvent
OnConfigurationChangedEvent
OnContentChangedEvent
OnContentViewAvailableEvent
OnCreateEvent
OnDestroyEvent
OnNewIntentEvent
OnPauseEvent
OnRestartEvent
OnResumeEvent
OnStartEvent
-
OnStopEvent
通過(guò)在activity中使用如下方法可以監(jiān)聽(tīng)這些事件:
<pre>
public void doSomethingOnResume( @Observes OnResumeEvent onResume ) {
Ln.d("Called doSomethingOnResume in onResume");
}
</pre>
使用@Observes這個(gè)注釋來(lái)觀察這個(gè)事件。
或者在activity中聲明一個(gè)監(jiān)聽(tīng)器來(lái)監(jiān)聽(tīng)事件
<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>
總結(jié)
RoboGuice作為一款依賴注入框架可以提供多種注入吠昭,比如視圖喊括、pojo類胧瓜、自定義類等。大量減少了findviewbyid和new的編寫瘾晃。
當(dāng)一個(gè)類依賴于另一個(gè)類時(shí)贷痪,需要在類中創(chuàng)建一個(gè)類的實(shí)例幻妓。當(dāng)使用了依賴注入后蹦误,所依賴的類的創(chuàng)建不在類中,而是在外部創(chuàng)建然后注入到類里面肉津。
與ButterKnife和xutils3的區(qū)別
缺點(diǎn)
- ButterKnife和xutils3的注入支持綁定事件和在Adapter中使用强胰,但是RoboGuice不可以,這是RoboGuice最大的缺點(diǎn)妹沙。
- Event只能在同一個(gè)Context中傳遞偶洋,感覺(jué)略雞肋。
優(yōu)點(diǎn)
- RoboGuice可以注入資源距糖、動(dòng)畫和系統(tǒng)服務(wù)等玄窝,減少了代碼量使代碼更加簡(jiǎn)潔。
- 依賴類的初始化不用在類中完成悍引,解耦恩脂。
- 可以通過(guò)@single、@contextsingle趣斤、@fragmentsingle來(lái)確定作用域俩块。
- @provide提供了強(qiáng)大的綁定類型能力。
- 可以綁定IntentExtra中的數(shù)據(jù)