【Android】クリックイベントの基本的な実装

# 概要

**よくあるやり方**

* 無名クラスのOnClickListenerを生成する
* クラスにimplementsする
* 個別クラスとして作成する

# 実装方法

前述の3種類について記載。

## 無名クラスのOnClickListenerを生成する

サッと作りたい時によくやる実装方法。
実装時間がかからず、Viewの持つクリックイベントを個別に管理できる。

ただしイベント数が増えると、記述しているメソッドが肥大化してしまい可読性を損なう。
またonCreateやonCreateView等のView生成メソッドで記述する場合、onClick()内の処理を
直接記述してしまうとライフサイクルメソッドとonClickイベントという2つの属性を持つ
ことになり、これまた可読性を損なう。

### 基本的な実装
```lang:Activity.java
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.hoge);

        findViewById(R.id.hogehoge).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // クリック時の処理
            }
        });

    }
```

本当に単純な処理を書くだけなら上記でも問題ないが、メソッドの肥大化を防ぐため
onClick内の処理もできるだけ別メソッド化していく。

```lang:Activity.java
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.hoge);

        findViewById(R.id.hogehoge).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                hogeClickEvent(v);
            }
        });

        findViewById(R.id.piyopiyo).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                hogeClickEvent(v);
            }
        });

        findViewById(R.id.fugafuga).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                fugaClickEvent(v);
            }
        });
    }

    private void hogeMethod(View v) {
        // 処理
    }

    private void piyoMethod(View v) {
        // 処理
    }

    private void fugaMethod(View v) {
        // 処理
    }
```

## クラスにimplementsする

画面内にボタン等のクリックイベントが多数存在する際によくやる実装方法。
クリックイベントの処理を一箇所にまとめることができる他、実装するクラスの中の
可読性も損ないにくい。

無名クラスのOnClickListenerを作成する場合と同様に、implementsしたonClick()の中に
長い処理を直接書くと、メソッドが肥大化しやすい。

### 基本的な実装

```lang:OnClickActivity.java
public class OnClickActivity extends Activity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.hoge);

        findViewById(R.id.hogehoge).setOnClickListener(this);
        findViewById(R.id.piyopiyo).setOnClickListener(this);
        findViewById(R.id.fugafuga).setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        if (v != null) {
            switch (v.getId()) {
                case R.id.hogehoge:
                    // クリック処理
                    break;
                
                case R.id.piyopiyo:
                    // クリック処理
                    break;
                
                case R.id.fugafuga:
                    // クリック処理
                    break;
                
                default:
                    break;
            }
        }
    }
}
```

メソッドの役割分担がハッキリしたが、内部処理が長くなる場合には、やはりメソッドの
肥大化を防ぐため、できるだけ別メソッドに処理を実装していく。
ただし内部処理が単純な場合はこの限りではなく、状況に応じて書き方を変えるべき。

## 個別クラスとして作成する

滅多にやることは無いが、実装方法を紹介。
手間はかかるが画面処理とクリックイベントを完全に分割でき、クラス毎のコード量が削減できる。

### 基本的な実装

```lang:OnClickActivity.java
public class OnClickActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.hoge);

        findViewById(R.id.hogehoge).setOnClickListener(OnClickEvent.getInstance());
        findViewById(R.id.piyopiyo).setOnClickListener(OnClickEvent.getInstance());
        findViewById(R.id.fugafuga).setOnClickListener(OnClickEvent.getInstance());

    }

}
```

```lang:OnClickEvent.java
public class OnClickEvent implements View.OnClickListener {

    private static final OnClickEvent instance = new OnClickEvent();

    private OnClickEvent() {
    }

    public static OnClickEvent getInstance() {
        return instance;
    }

    @Override
    public void onClick(View v) {
        if (v != null) {
            switch (v.getId()) {
                case R.id.hogehoge:
                    // クリック処理
                    break;

                case R.id.piyopiyo:
                    // クリック処理
                    break;

                case R.id.fugafuga:
                    // クリック処理
                    break;

                default:
                    break;
            }
        }
    }

}
```

小数かつ重要な機能の場合、それぞれに専用クラスを作成してしまう手もある。

```lang:OnClickActivity.java
public class OnClickActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.hoge);

        findViewById(R.id.hogehoge).setOnClickListener(OnClickHogeEvent.getInstance());
        findViewById(R.id.piyopiyo).setOnClickListener(OnClickPiyoEvent.getInstance());
        findViewById(R.id.fugafuga).setOnClickListener(OnClickFugaEvent.getInstance());

    }

}
```

# まとめ

同一プロジェクト内に複数の実装方法が存在しても仕方ない、くらいの気持ちで良いかもしれないが
それぞれの方法を適切に使い分けることを意識しなければならない。