roboguice
※※※ 注意 ※※※
このページの翻訳は途中ですが、今後メンテナンスされません。 そもそも、Androidのリソースシステムの「設計」自体が間違っており、開発者にとって非常に使いづらいものになってしまっています。 それをなんとか救おうとしているのがroboguiceであると考えるからです。 このような場当たり的な対応を行うよりも、Androidシステムそれ自体を修正すべきであると考えます。
※※※ 注意 ※※※
リンク
roboguice - Google Guice on Android
概要
要するに、Guiceをandroid上で便利に利用するためのサポートライブラリ。 特にこれがなければandroidでGuiceできないというわけではないが、あった方が全然便利。
※ただし、もともとguiceのAOP機能はandroidのような実行のバイトコード生成をサポートしていないプラットフォームでは使用できないことに注意。 http://code.google.com/p/google-guice/downloads/listのダウンロードリストにも、AOP無しバージョンについてわざわざ「Suitable for android」と注意書きしている。
素人による翻訳
※以下は素人による翻訳です。
トップページ
原文:roboguice - Google Guice on Android
RoboguiceはAndroidの開発における欠点をいくつかの欠点を解消して、物事を簡単にし、楽しくする。 getIntent().getExtra()したときにいつもnullチェックを忘れないだろうか?RoboGuiceはこれをやってくれる。 findViewById()をTextViewにキャストするのは不要と思わないだろうか?RoboGuiceはこれをやってくれる。
RoboGuiceは開発における推測を行う。もはや、bindService()を用いてユーザサービスを取得する必要はなく、getSystemService()を用いてシステムサービスを取得すればよいのだ(訳注:???)。 View, Serviceあるいはいかなるオブジェクトであってもそれを注入してくれ、RoboGuiceに詳細を任せることができる。
RoboGuiceはアプリケーションコードをスリム化する。 短いコードはバグの出現率も低い。 それに追跡しやすくなる。 もはや、androidぷらっとフォームのメカニックスが散らばったコードではなく、アプリ特有のロジックにフォーカスすればよいのだ。
マジックなどない。これらすべてはあなた自身がRoboGuiceを使って明示的に構成あるいはオーバライドする必要がある。
RoboGuiceアプリケーションはAndroidマーケットに過去数カ月に渡ってフィーチャーされてきた。 これはGoogle Guiceライブラリを利用して単純な依存性注入を、モバイルアプリケーション用に軽く行うものである。
きちんと動き、人々に使われている。Why not give it a spin?
簡単な例
※原文:http://code.google.com/p/roboguice/wiki/SimpleExample
RoboGuiceはandroidに単純で容易な依存性注入をもたらすフレームワークであり、Guiceを使用している。 もし今までにSpringやGuiceを使ったことがあるなら、既にこのスタイルのプログラミングがいかに便利であるかを実感しているだろう。
以下の簡単な例をみてみよう。これは典型的なAndroidアクティビティだ。
class AndroidWay extends Activity {
TextView name;
ImageView thumbnail;
LocationManager loc;
Drawable icon;
String myName;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
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 );
}
} この例は18行からなるコードである。 onCreate()を見てみると、5行ものボイラープレート初期化を行って、たった一つのname.setText()という目的にたどりついていることがわかる。 複雑なアクティビティはもっと多くのこの手のコードが必要になる。
RoboGuiceを使った次のコードを比較してみよう。
class RoboWay extends GuiceActivity {
@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 );
}
} この例では、onCreate()はとても読むのが簡単になっている。 プラットフォームボイラープレートはすべて取り除かれ、君自身のビジネスロジックのみに集中している。 SystemServiceは必要かい?一つ注入しよう。 ViewやResouceは必要かい?それらも注入しよう。RoboGuiceにその詳細を任せよう。
RoboGuiceのゴールは、君自身のコードを作成してもらうことだ。Androidにおいてメンテナンスが必要なすべての初期化やライフサイクルコードではなく。
インストレーションページにいって、君の最初のRoboGuiceアプリケーションの構成方法の詳細を見てみよう。
追加の例)
RoboGuiceの使用法マニュアルは、まだまだすべき姿になっていないのだが、君が開始するために必要なサンプルを提供している。 RoboGuiceで何ができるかを知りたいのであれば、samplesディレクトリ中のAstroboy exampleを参照してほしい。
インストレーション
※原文:http://code.google.com/p/roboguice/wiki/Installation
ダウンロードとインストール
RoboGuiceとguice-2.0-no_aop.jarをダウンロードすること。
新規のAndroidプロジェクトを作成する(あるいは既にあるものを使う)、少なくともplatform 1.5, API level 3 and SDK Version 3をターゲットとする。
二つのjarファイルを君のAndroidプロジェクトのビルドパスに含める(Eclipse : Project > Properties > Java Build Path > Libraries > Add External JARs)
最初のRoboGuiceアプリケーション
※訳注:ここはGuiceを使ったことがないと、何をやっているのかわからないと思われる。
GuiceApplicationをextendsする新しいクラスを作成する(MyApplicationとしよう)。
アプリケーションのAndroidManifest.xml中のandroid:name属性として、新規作成したアプリケーションを設定する。 例えば、この例では以下のようになる。
<application android:icon="@drawable/icon" android:label="@string/app_name" android:name="com.mycompany.myproject.MyApplication">
AbstractAndroidModuleをextendsするconfiguration moduleクラスを作成する(MyModuleとしよう)。 configure()メソッドを実装して、君自身のバインディングを設定する。 モジュールのconfigureについてはGuiceのWikiを参照すること:http://code.google.com/p/google-guice/wiki/GettingStarted
君のアプリケーションクラス中でGuiceApplication.addApplicationModules(List<Module>)メソッドをオーバライドする。 リストに君のカスタムモジュールのインスタンスを追加する。例えば、
public class MyApplication extends GuiceApplication {
protected void addApplicationModules(List<Module> modules) {
modules.add(new MyModule());
}
}君のアクティビティをActivityクラスをextendsさせるのではなく、GuiceActivityをextendsするように書き換える。
さて、これでGuiceを使う準備は整った。何ができるのかを知りたいならsamplesディレクトリのAstroboy exampleを参照してくれ。
Atroboy example
※astroboyとは鉄腕アトムのこと。
/*
* Copyright 2009 Michael Burton
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions
* and limitations under the License.
*/
package roboguice.astroboy.activity;
import roboguice.activity.RoboActivity;
import roboguice.astroboy.AstroboyModule;
import roboguice.astroboy.R;
import roboguice.astroboy.bean.*;
import roboguice.astroboy.service.TalkingThing;
import roboguice.inject.ExtrasListener;
import roboguice.inject.InjectExtra;
import roboguice.inject.InjectResource;
import roboguice.inject.InjectView;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
import com.google.inject.Inject;
import com.google.inject.internal.Nullable;
import java.util.Date;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNull;
public class DoctorTenma extends RoboActivity {
// 任意のView, Stringあるいは他のタイプのリソースを注入できる。
// 詳細はResourceListenerを参照のこと。
@InjectView(R.id.widget1)
protected TextView helloView;
@InjectResource(R.string.hello)
protected String hello;
/**
* このアクティビティをスタートしたintentのextraを{@link InjectExtra}で注入することができる。
* このアノテーションは基本的には以下のコードと等価である。
* {@code
* nameExtra=getIntent().getStringExtra("nameExtra");}
*
* @see ExtrasListener
*/
@InjectExtra("nameExtra")
protected String nameExtra;
/**
* {@link InjectExtra}アノテーションに{@code optional=true}を指定しない場合には、
* このアクティビティへの注入時にextraが存在していなければならない。
* optionalがtrueで、かつextraが見つからないときには、このフィールドには何も注入されない。
*/
@InjectExtra(value = "optionalExtra", optional = true)
protected Date myDateExtra = new Date(0);
/**
* {@link InjectExtra}のデフォルト動作は、null値を禁止している。
* しかし、もしnull値の注入を許したいのであれば、{@link Nullable}アノテーションを
* 使わなければならない。
* 以下の例では、nullExtraは存在しなければならないが、しかしnullでも構わない。
*/
@InjectExtra("nullExtra")
@Nullable
protected Object nullInjectedMember = new Object();
/**
* This example shows how to inject a bean converted from an extra value
* using a provider. The String extra is converted into a Person. See
* {@link PersonFromNameExtraProvider} to see how a Person is created. A
* binding is actually done in {@link AstroboyModule}.<br />
* <br />
* The extra key is defined in the provider. This is useful if you want to
* inject a bean created from multiple extra values (e.g. creating a person
* from its name and age).
*/
@Inject
protected Person personFromExtra;
/**
* This is a more flexible way to inject a bean : a converter is configured
* and bound, and RoboGuice uses this converter to create a Person from a
* String extra. See {@link PersonExtraConverter} and {@link AstroboyModule}
* .
*/
@InjectExtra("nameExtra")
protected Person personFromConvertedExtra;
/**
* This date is injected using the converter {@link DateExtraConverter} that
* converts a {@link Long} to a {@link Date}.
*/
@InjectExtra("timestampExtra")
protected Date dateFromTimestampExtra;
/**
* This date is injected using the converter {@link DateTwiceExtraConverter}
* that converts an {@link Integer} (doubled) to a {@link Date}.
*/
@InjectExtra("timestampTwiceExtra")
protected Date dateFromTimestampTwiceExtra;
// You can inject various useful android objects.
// See GuiceApplication.configure to see what's available.
@Inject
protected SharedPreferences prefs;
// Injecting a collaborator
@Inject
protected TalkingThing talker;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); // Injection doesn't happen until you
// call setContentView()
helloView.setText(hello + ", " + this.getClass().getSimpleName());
helloView.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
startActivity(new Intent(DoctorTenma.this, AstroPrefActivity.class));
}
});
assertEquals(prefs.getString("dummyPref", "la la la"), "la la la");
assertNull(nullInjectedMember);
assertEquals(myDateExtra, new Date(0));
assertEquals(nameExtra, "Atom");
assertEquals(personFromExtra.getName(), "Atom");
assertEquals(personFromExtra.getAge().getTime(), 3000L);
assertEquals(personFromConvertedExtra.getName(), "Atom");
assertEquals(dateFromTimestampExtra.getTime(), 1000L);
assertEquals(dateFromTimestampTwiceExtra.getTime(), 2000L);
Log.d("DoctorTenma", talker.talk());
}
}