Android 依賴注入框架RoboGuice
概述
在開發應用時一個基本原則是模組化,並且盡最大可能性地降低模組之間的耦合性。Dependency injection 大大降低了類之間的依賴性,可以通過annotation描述類之間的依賴性,避免了直接呼叫類似的建構函式或是使用Factory來參加所需的類,從而降低類或模組之間的耦合性,以提高程式碼重用並增強程式碼的可維護性。
Google Guice提供了Java平臺上一個輕量級的 Dependency injection 框架,並可以支援開發Android應用。本指南將使用Android平臺來說明Google Guice的用法。(其他類似框架有Dagger,Buffernife)
RoboGuice 為Android平臺上基於Google Guice開發的一個庫,可以大大簡化Android應用開發的程式碼和一些繁瑣重複的程式碼。比如程式碼中可能需要大量使用findViewById在XML中查詢一個View,並將其強制轉換到所需型別,onCreate 中可能有大量的類似程式碼。RoboGuice 允許使用annotation 的方式來描述id於View之間的關係,其餘的工作由roboGuice庫來完成。
RoboGuice主要功能:
- 控制元件注入:用@InjectViews方法初始化控制元件,例如:@InjectView(R.id.textview1)TextView textView1。
- 資源注入:用@InjectResources方法初始化資源,例如:@InjectResource(R.string.app_name)String name。
- 系統服務注入:用@Inject方法初始化並獲取系統服務,例如:@Inject LayoutInflater inflater。
- POJO物件注入:用@Inject方法注入並初始化POJO物件,例如:@Inject Foo foo。
以下示例對比看看RoboGuice的作用:
不使用RoboGuice:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
name = (TextView) findViewById(R.id.name);
thumbnail = (ImageView) findViewById(R.id.thumbnail);
loc = (LocationManager) getSystemService(Activity.LOCATION_SERVICE);
icon = getResources().getDrawable(R.drawable.icon);
myName = getString(R.string.app_name);
name.setText( "Hello, " + myName );
}
}
使用RoboGuice: @ContentView(R.layout.main)
class RoboWay extends RoboActivity {
@InjectView(R.id.name) TextView name;
@InjectView(R.id.thumbnail) ImageView thumbnail;
@InjectResource(R.drawable.icon) Drawable icon;
@InjectResource(R.string.app_name) String myName;
@Inject LocationManager loc;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
name.setText( "Hello, " + myName );
}
}
使用前準備工作
RoboGuice官方Demo: https://github.com/roboguice/roboguice/tree/master/astroboy
安裝
方式一:新增依賴庫:(不推薦,在androidStudio上報錯,很詭異。不知道為什麼)
- RoboGuice 3.0
- RoboBlender 3.0
- jsr330 javax.inject (JSR-330 support)
- jsr305 (optional support for @Nullable annotation, if desired)
方式二:在build.gradle中的dependecies片段中新增:(推薦)
dependencies {
provided 'org.roboguice:roboblender:3.0'
compile 'org.roboguice:roboguice:3.0'
}
參考https://github.com/roboguice/roboguice/wiki/InstallationNonMaven
繼承類:
activities, services, and fragments都需要繼承自RoboGuice提供的下列類:
- RoboActivity
- RoboListActivity
- RoboExpandableListActivity
- RoboMapActivity
- RoboPreferenceActivity
- RoboAccountAuthenticatorActivity
- RoboActivityGroup
- RoboTabActivity
- RoboFragmentActivity
- RoboLauncherActivity
- RoboService
- RoboIntentService
- RoboFragment
- RoboListFragment
- RoboDialogFragment
- etc.
Injection
- Inherit from RoboActivity
- Set your content view
- Annotate your views with @InjectView
public class MyActivity extends RoboActivity {
@InjectView(R.id.text1) TextView textView;
@Override
protected void onCreate( Bundle savedState ) {
setContentView(R.layout.myactivity_layout);
textView.setText("Hello!");
}
}
@ContentView註解: @ContentView(R.layout.myactivity_layout)
public class MyActivity extends RoboActivity {
@InjectView(R.id.text1) TextView textView;
@Override
protected void onCreate( Bundle savedState ) {
textView.setText("Hello!");
}
}
將View注入Fragment@InjectView
由於Fragment中的依賴注入發生在onViewCreated()中,所以需要在onViewCreated中呼叫super.onViewCreate()之後才能使用注入的View.
注意這裡的:onViewCreated是在onCreateView呼叫之後恢復儲存的狀態到View之前立馬呼叫,
@InjectView TextView commentEditText;
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
commentEditText.setText("Some comment");
}
注入Resource到Activity:@InjectResource
public class MyActivity extends RoboActivity {
@InjectResource(R.anim.my_animation) Animation myAnimation;
}
注入System Service:@Inject
class MyActivity extends RoboActivity {
@Inject Vibrator vibrator;
@Inject NotificationManager notificationManager;
注入POJO:@Inject
注意:需要提供一個無引數構造器
class MyActivity extends RoboActivity {
@Inject Foo foo; // this will basically call new Foo();
}
當然如果不想使用預設構造器,可以註解構造器:class Foo {
Bar bar;
@Inject
public Foo(Bar bar) {
this.bar = bar;
}
}
也可以註解POJO的Field:class Foo {
@Inject Bar bar;
// Roboguice doesn't need a constructor, but you might...
}
注入Singleton
前提:對單例類使用@Singleton@Singleton //a single instance of Foo is now used though the whole app
class Foo {
}
class MyActivity extends RoboActivity {
@Inject Foo foo; // this will basically call new Foo();
}
注意:這個單例一旦建立會一直駐留記憶體,其他類似的還有@ContextSingleton,@FragmentSingletion,他們的作用範圍比較小,利於垃圾回收。自定義Binding
public interface IFoo {}
public class Foo implements IFoo {}
public class MyActivity extends RoboActivity {
//How to tell RoboGuice to inject an instance of Foo ?
@Inject IFoo foo;
}
步驟:
1.向AndroidManifest.xml中新增meta-data
<application ...>
<meta-data android:name="roboguice.modules"
android:value="com.example.MyModule,com.example.MyModule2" />
</application>
2.繼承AbstractModulepublic 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));
}
}
注入到Service與BroadcastReceiver:
public class MyService extends RoboService {
@Inject ComputeFooModule computeFooModule;
public class MyBroadcastReceiver extends RoboBroadcastReceiver {
@Inject ComputeFooModule computeFooModule;
注入到自定義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);//注意這一行,為了使其正常工作。
}
public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
inflate(context,R.layout.my_layout, this);
RoboGuice.getInjector(getContext()).injectMembers(this);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
inflate(context,R.layout.my_layout, this);
RoboGuice.getInjector(getContext()).injectMembers(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 Event
public class MyActivity extends RoboActivity {
// 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");
}
// As you might expect, some events can have parameters. The OnCreate event
// has the savedInstanceState parameter that Android passes to onCreate(Bundle)
public void doSomethingElseOnCreate( @Observes OnCreateEvent onCreate ) {
Ln.d("onCreate savedInstanceState is %s", onCreate.getSavedInstanceState())
}
// And of course, you can have multiple listeners for a given event.
// Note that ordering of listener execution is indeterminate!
public void xxx( @Observes OnCreateEvent onCreate ) {
Ln.d("Hello, world!")
}
}
本文還有很多特性沒有介紹到,後續可能會進行補充。
參考:
http://www.oschina.net/p/roboguice
https://github.com/roboguice/roboguice/wiki
http://mobile.51cto.com/abased-426620.htm
相關文章
- Android依賴注入:Dagger、RoboGuice和ButterKnifeAndroid依賴注入GUI
- spring框架學習 依賴注入Spring框架依賴注入
- 三大框架---angular---依賴注入框架Angular依賴注入
- 簡單談談Hilt——依賴注入框架依賴注入框架
- angular依賴注入Angular依賴注入
- XUnit 依賴注入依賴注入
- Struts 依賴注入依賴注入
- 依賴倒置(DIP)與依賴注入(DI)依賴注入
- 依賴注入?依賴注入是如何實現解耦的?依賴注入解耦
- 放棄dagger?Anrdoi依賴注入框架koin依賴注入框架
- Util應用框架基礎(一) - 依賴注入框架依賴注入
- ASP.NET Core中的依賴注入(2):依賴注入(DI)ASP.NET依賴注入
- [譯] 依賴注入?? 哈??依賴注入
- Angular 依賴注入原理Angular依賴注入
- .Net Core — 依賴注入依賴注入
- 理解 Angular 依賴注入Angular依賴注入
- Spring依賴注入Spring依賴注入
- Spring依賴注入---Spring依賴注入
- 依賴注入系列教程依賴注入
- 我看依賴注入依賴注入
- webapi - 使用依賴注入WebAPI依賴注入
- 依賴注入是否值得?依賴注入
- Android依賴注入之BufferKnife 8.0註解使用Android依賴注入
- 搞定Go單元測試(四)—— 依賴注入框架(wire)Go依賴注入框架
- 200行Java程式碼實現依賴注入框架Java依賴注入框架
- Spring框架之IOC/DI(控制反轉/依賴注入)Spring框架依賴注入
- Asp .Net Core 依賴注入依賴注入
- Spring IOC——依賴注入Spring依賴注入
- 入門系列-依賴注入依賴注入
- C# 依賴注入 & MEFC#依賴注入
- Spring 依賴注入 DISpring依賴注入
- 關於依賴注入(typescript)依賴注入TypeScript
- 什麼是依賴注入依賴注入
- .NET8 依賴注入依賴注入
- spring 的依賴注入Spring依賴注入
- 深入淺出依賴注入依賴注入
- C# Unity依賴注入C#Unity依賴注入
- JavaScript裡的依賴注入JavaScript依賴注入