なか日記

一度きりの人生、楽しく生きよう。

Android Bindingを使ってみた(2)

Android Bindingを使ってみた(1) - タイトルは未定の続きです。

もう少しAndroid Bindingメリットを享受するために、ActivityとViewModelを分離してみます。

目的は「ViewModelをAndroidのクラスに依存しない様にする」です。
その理由は「ViewModelのUnitTestがAndroidの実機やエミュレータなしに行える様になる」ということになります。

ソース一式はこちら
https://github.com/nakaji/AndroidBindingSample

最初に

ViewModelにはStringObservable型のメンバやCommandを実装したメンバを移動することになりますが、CommandクラスのInvokeは引数が以下の様になっており、Viewを抱え込んでいます。

public void Invoke(View arg0, Object... arg1) {

つまり、CommandをViewModelに持って行ったとしてもAndroidのクラスへの依存は残ってしまいます。


そこで、PojoViewModelを使用することでこの問題を解消します。

PojoViewModelの概要は以下の通りです*1

PojoViewModel - android-binding - Pojo (Plain-Old-Java-Object) View Model support

Introduction
序論

Currently experimenting Pojo-styled (Plain-Old-Java-Object) View Models.
現在実験中であるPojoスタイルのView Modelです。

Such View Models no longer need the Observables nor Commands but simply defined their own binding-interfaces as normal object:
このView ModelはObservablesやCommandsを必要とせず、通常のオブジェクトの様に、シンプルに定義されたバインディング用のインターフェースを必要とします。

  • Commands: Plain 'void' Method with No arguments
  • Commands:引数や戻り値のないシンプルなメソッド
  • Observables: Private fields with public getters and/or setters
  • Observables: puulicなセッターやゲッターとprivateなフィールド

The only requirement for the ViewModel is it need to implements the PojoViewModel interface.
ViewModelが必要とする唯一の要件は、PojoViewModelインターフェースを実装することです。

実装の変更方針

いきなりActivityとViewModelに分けると分離作業とPojoViewModelの実装を平行して行うことになり、作業が複雑になります。
今回は一旦ActivityにPojoViewModelを実装し、それからActivityとViewModelに分離することにします。

AndroidBindingSampleActivity

PojoViewModelインターフェースの実装

10行目付近までお決まりの書き方になります。
PojoViewModelをimplementsすれば、大部分をeclipseが実装してくれます。

setBMI

データが変更されたことを通知するためにメンバ変数の更新はsetter経由で更新します。

getBMI

Viewが参照するgetterになります。

onCreate

Binder.setAndBindContentViewする部分が以下の様に変わっています。

Binder.setAndBindContentView(this, R.layout.main, this);

 ↓

Binder.setAndBindContentView(this, R.layout.main, PojoViewModelWrapper.create(this));
ソース
public class AndroidBindingSampleActivity extends Activity implements PojoViewModel {

    private PojoViewModelHelper helper = new PojoViewModelHelper();

    public PojoViewModelHelper getHelper() {
        return helper;
    }

    public void notifyPropertyChanged(String propertyName) {
        helper.notifyPropertyChanged(propertyName);
    }

    private EditText heightText;
    private EditText weightText;
    private double _bmi;

    public void setBMI(double bmi) {
        _bmi = bmi;
        notifyPropertyChanged("BMI");
    }

    public String getBMI() {
        return "Your BMI is " + String.valueOf(_bmi);
    }

    public void Calculate() {
        double height = Integer.valueOf(heightText.getText().toString());
        double weight = Integer.valueOf(weightText.getText().toString());
        double bmi = weight / Math.pow(height / 100.0, 2);
        setBMI(bmi);
    };

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Binder.init(this.getApplication());
        Binder.setAndBindContentView(this, R.layout.main, PojoViewModelWrapper.create(this));

        heightText = (EditText) findViewById(R.id.height);
        weightText = (EditText) findViewById(R.id.weight);
    }
}

レイアウト(View)

ボタン

AndroidBindingSampleActivityのCalculateメソッドにバインドしています。

テキスト

AndroidBindingSampleActivityのgetBMIにバインドされることになります。

ソース(抜粋)
	<Button
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:text="計算"
		binding:onClick="Calculate"
		/>

	<TextView
		android:id="@+id/buttonCalculateBMI"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		binding:text="BMI"
		/>

おしまい

これでPojoViewModelの実装が終わりました。次はActivityとViewModelの分離を行いたいと思います。

*1:オレオレ意訳なので微妙に間違ってたらごめんなさい