Hello Guice! Androidアプリの作成
実際に使ってみる
Hello World!を Guiceで作る
- GreetingService
名前を入力すると挨拶を返すサービスのインターフェース - StandardGreetingService
実際にGreetingServiceの実装。普通の挨拶を返す - Client
GreetingServiceを利用するクラス - GreetingModule
GreetingServiceのインタフェースと実装を結びつけるモジュール
GreetingModuleクラスですが、DI Containerにおける設定ファイル 「このインターフェースが要求されたこの実装を使う」といった設定はこの中に書かれる形になります。
Guiceの特徴として設定ファイルである Moduleがコンパイラを経由する事で XMLファイルのようにタイプミスが実行時までわからないといった事を防げます。
実装
Androidの Application Projectに変更を加えていきます。
layoutファイル
テキスト表示用にTextViewを追加
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/main_activity_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="@string/hello_world"
tools:context=".MainActivity">
</RelativeLayout>
サービスのインターフェース
package local.exguice1;
public interface GreetingService {
String greetingTo(String to_name);
}
サービスの実装
package local.exguice1;
public class StandardGreetingService implements GreetingService {
public String greetingTo(String to_name) {
return to_name + "さん、こんにちは!";
}
}
サービスを利用するクライアント
ポイントは @Inject というfieldに付けられたアノテーション。
package local.exguice1;
import javax.inject.Inject;
public class Client {
@Inject
private GreetingService service;
public String getMessage() {
return service.greetingTo("Google Guice");
}
}
GreetingServiceを利用するためのModule
bind関数を呼び出して GreetingServiceとして StandardGreetingServiceを注入
package local.exguice1;
import com.google.inject.AbstractModule;
public class GreetingModule extends AbstractModule {
@Override
protected void configure() {
bind(GreetingService.class).to(StandardGreetingService.class);
}
}
MainActivity
やってることは Injectorを使ってインスタンスを得るようにしています。
Injectorのインスタンス作成には 設定ファイル代わりの Moduleを指定する。
package local.exguice1;
import com.google.inject.Guice;
import com.google.inject.Injector;</span>
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.TextView;
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Injector injector = Guice.createInjector(new GreetingModule());
Client client = injector.getInstance(Client.class);
TextView textView = (TextView) findViewById(R.id.main_activity_textview);
textView.setText(client.getMessage());
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
まとめ
@Injectアノテーションを付けられたフィールドがfield injectionの対象
Module.configure内で Interface と Implementation を bindしている。 bind(Interface).to(Implementation); の方法は Linked Bindingsと呼ばれる。
injectorから getInstanceすると @Injectフィールドに 指定実装が注入された インスタンスが得られて利用できます。
Interfaceに対する Implementationの注入を Moduleに追い出せた形。