Androidアプリでも、JavaのGUI開発と同様に「ユーザーの操作に応じた処理」を書く必要があります。たとえば「ボタンが押されたときに何かをする」などです。
しかし、Android特有の書き方や慣習があり、Swing/AWTなどに慣れたJavaエンジニアにとっては「なんか書き方が違うぞ」と違和感を覚える場面があります。
■ JavaのGUIでの典型的なイベントリスナーの書き方(例:Swing)
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("ボタンが押された!");
}
});
このように、明示的にインターフェースを実装して、イベント処理を書くのが定番です。
■ Androidでの典型的な書き方(匿名クラス or ラムダ式)
Button button = findViewById(R.id.clickButton);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("MainActivity", "ボタンが押された!");
}
});
または、Java 8 以降ならラムダ式も使えます:
button.setOnClickListener(v -> {
Log.d("MainActivity", "ボタンが押された!");
});
■ 違和感ポイント①:イベントリスナーがView.OnClickListener
?
Java経験者だと、「ActionListener
じゃないの?」「なんでViewがListenerを定義してるの?」と思うかもしれません。
これはAndroidの設計思想によるものです。
- Androidでは全てのUI部品(View)は
View
を継承している - だから「ボタンのクリックリスナー」ではなく「Viewのクリックリスナー」として定義されている
- 結果として、ボタンもテキストも画像も、全部
setOnClickListener()
で処理できるようになっている
つまり、Listenerの粒度が広く統一されていると考えると納得がいきます。
■ 違和感ポイント②:インターフェースを直接使わず、メソッドで登録?
JavaのGUIでは addListener()
という命名が多いのに対し、Androidでは setOnClickListener()
のように “set~” の形でリスナーを登録します。
これは、「リスナーは1つしか設定できない」ことを示しています。
button.setOnClickListener(...); // 上書きされる
イベントを1つの処理に絞る設計になっており、複数のリスナーを追加することはできません(同時に複数の処理を走らせたい場合は、1つのonClick内で複数の処理を呼び出します)。
■ 違和感ポイント③:イベント引数が独自のView v
Javaでは ActionEvent e
のようにイベント情報を持つオブジェクトが渡されますが、Androidでは基本的に押されたViewそのもの(View v
)が引数になります。
そのため、同じリスナーを複数のボタンに使って、v.getId()
でどのボタンかを判別するケースもよくあります。
View.OnClickListener listener = v -> {
if (v.getId() == R.id.button1) {
// ボタン1が押された
} else if (v.getId() == R.id.button2) {
// ボタン2が押された
}
};
■ まとめ:Androidのイベントリスナーは「統一されたViewベース」
項目 | Java GUI(Swing等) | Android |
---|---|---|
イベント対象 | 明示的な部品(JButtonなど) | すべてのView(Button含む) |
リスナー定義 | ActionListener など明示的 | View.OnClickListener など |
登録方法 | addXXXListener() | setXXXListener() |
引数 | ActionEvent など | 押されたView そのもの |
Androidでは「部品=View」「イベント=Viewへの操作」として抽象化されているため、最初は戸惑っても、慣れれば汎用的に書けるようになります。