2011年6月21日火曜日

Androidでも流れるインターフェース

無駄に流れるインターフェースでOnClickListenerを実装してみた。

まずはアプリの仕様から。

画面仕様
  • 最初の画面はTextViewButtonで構成される。
  • Buttonをクリックすると、次の画面に移動する。
  • 次の画面はTextViewButtonで構成される。
  • Buttonをクリックすると、最初の画面に移動する。

非常に単純な作りですね。
ちなみにこれは次の記事でテストを書くのでよく覚えておいてね。


で、百聞は一見にしかずで、これまた画面の動きをハードコピーしました。


この画面で「push me!」を押すと、


この画面になります。

多分、Androidをやっている人たちなら、この画面簡単に作れちゃうでしょう。
いや実際オレも30分くらいで完成しました。
では、これからオレがdisるコード例を示します。


class MainActivity extends Activity{
    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        View view = findViewById(R.id.button);
        view.setOnClickListener(
            new OnclickListener(){
                @Override
                public void onClick(View v){
                    Intent intent = new Intent(this,
                            NextActivity.class);
                    startActivity(intent);
                }
            }
        );
    }
}


読みづらいですね。
まだ、OnClickListenerがひとつだからいいものの、複数のViewにボタンを設定するとなったら、発狂しそうですね。

というわけで、オレが実装したのは次のようなコードです。

class MainActivity extends Activity{
    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        Create.activity(NextActivity.class)
            .from(this)
            .listenOn(R.id.button);
    }
}


インターフェースを単純につくっています。
まずはインターフェースから。


interface MoveActivity extends OnClickListener{

    public MoveActivity from(Activity preActivity);

    public MoveActivity to(Class<? extends Activity> nextActivity);

    public MoveActivity listenOn(int view);
}


インターフェースはこれだけです。
前のエントリとほとんど変わりません。変わったのはlistenOn(int view)を付け加えたあたりですね。
したがって、これを実装したクラスのテスト性もほとんど変わりません。

これの実装が頑張りどころです。

class Create implements MoveActivity {

    private Activity preActivity;
    private Class<? extends Activity> nextActivity;

    public static MoveActivity activity(
            Class<? extends Activity> newActivity){
        return new Create()
                .to(newActivity);
    }

    @Override
    public MoveActivity from(Activity preActivity){
        this.preActivity = preActivity;
        return this;
    }

    @Override
    public MoveActivity to(Class<? extends Activity> nextActivity){
        this.nextActivity =  nextActivity;
        return this;
    }

    @Override
    public MoveActivity listenOn(int view){
        preActivity.findViewById(view).setOnClickListener(this);
        return this;
    }

    @Override
    public void onClick(View view){
        Intent intent = new Intent(preActivity, nextActivity);
        preActivity.startActivity(intent);
    }
}


ここのポイントは普通ならgetInstance(Class<? extends Activity>)とやるメソッド名を、activity(Class<? extends Activity>)としている所です。Javaに慣れている方には若干読みづらく感じますが、あまりJavaに詳しくない人でもこれならActivityを組み立てることできますね。

あともうひとつのポイントは返す型はかならずインターフェースにすること。

これはDevLove Hangar Flight で矢野さんがおっしゃっていた、Javaの型とはクラスではなく、インターフェースのことだというインターフェース原理主義に即しています。これなら、Androidのバージョンが変わってAPIが変更されてもActivity部分は変えなくて済みますからね。

0 件のコメント:

コメントを投稿