【Android】onClickか、OnClickListenterか。【違いを比較】

  • このエントリーをはてなブックマークに追加
  • LINEで送る

こんにちは、ふりいです。

画面にあるボタンがクリックされた時の処理の実装方法は大きく2つあるようです。
今回は、その2つについて解説していこうと思います。

これまでに作ったソースコードとも見比べながら、それぞれの特徴を見ていきます。
また、結局どちらを使うべきかについても考えていきましょう。

Contents

onClickを使った実装方法について

先日、ボタンをクリックするとダイアログ画面が表示されるコードを書きました。
詳しくは以下を参照してみて下さい。
≫参考:現役SEがゼロから作るAndroidアプリ構築【デモ作成①~改良編~】

こちらはonClickを使った実装となっていることがわかりますね。
xmlファイルの中に、「onClick」という属性を指定しています。

activity_main.xml

android:onClick="showHandOverDialog"

そして、指定したメソッド名に対応する処理をactivity側で実現するという流れですね。
activity側は、以下の部分が該当します。

MainActivity.java

public void showHandOverDialog(View view) {
    HandOverDialogFragment handOverDialogFragment = new HandOverDialogFragment();
    handOverDialogFragment.show(getSupportFragmentManager(), "dialog");
}

onClickのメリット・デメリット

onClickについての実装方法はわかりました。
次にメリット・デメリットについても見ていきます。

まずメリットですが、以下のような感じでしょうか。

・xmlにもjavaにもメソッド名が書かれているので、対応関係がわかりやすい。
・どのボタンが、どのメソッドを実行するのかがxmlを見るとわかる。
・簡単にメソッドを追加できる。

xmlとjavaの両方に記載する必要があるので、相互の関係性は把握しやすいですね。
一方でデメリットはどのようなものが考えられるかというと、

・変更・削除時に、xmlもjavaも修正する必要があり面倒。
・javaを見ただけでは、どの画面で実行されるメソッドがわかりにくい。
・xmlのコードのボリュームが膨大になると、onClickを探すに苦労しそう。

xmlをいじらないといけない点がデメリットにもなり得るのかなと感じました。
また、何かあった時に2か所直さないといけなくなりそうなのも少し気になりますね。

OnClickListenterを使った実装方法について

次に、OnClickListenterを使ってのダイアログの表示方法について見ていきます。
ここまで一緒にコードを書いてくれている方のために、onClickありの状態から変える感じで進めます。

onClickありのソースからonClick関連のコードを削ると、以下のようになります。
少し長くなってしまいますが、コードをまるっとコピーできるようにしてあります。
(今回は「HandOverDialogFragment.java」は変更しません)

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".activity.MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/floatingActionButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.867"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.941"
        app:srcCompat="@android:drawable/ic_menu_add" />

</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.java

package com.example.app.activity;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import com.example.app.R;

public class MainActivity extends AppCompatActivity {

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

上記のコードを修正していきます。
OnClickListenterを用いた実装では、xmlに対しての修正はありません。
よって、javaの方をがっつり変更します。

参考にするのは、以下の記事です。
≫参考:フローティング操作ボタンを追加する - Android デベロッパー

先に変更後のコードですが、このようになりました。

MainActivity.java


package com.example.app.activity;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import com.example.app.ui.HandOverDialogFragment;
import com.example.app.R;
import com.google.android.material.floatingactionbutton.FloatingActionButton;

public class MainActivity extends AppCompatActivity {

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

        FloatingActionButton fab = findViewById(R.id.floatingActionButton);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                HandOverDialogFragment handOverDialogFragment = new HandOverDialogFragment();
                handOverDialogFragment.show(getSupportFragmentManager(), "dialog");
            }
        });
    }
}

18~25行目を追加したような状態ですね。
各行について、簡単に補足します。

18行目では、ボタンID(=floatingActionButton)から、対応するビューの情報を取得しています。
floatingActionButtonは「activity_main.xml」で設定しているIDで、今回はボタンと紐づきます。

19行目からは、Javaでシステム開発をやっている私には、そんなに見かけない形です。
「fab.setOnClickListener」の中身として設定されているのは、匿名クラスというやつです。

匿名クラスは、簡単にクラス定義とインスタンス生成ができちゃう代物ですね。
本来なら、クラスを作る場合にはクラス名をつけたりする必要があります。
しかし、匿名クラス(無名クラス)を使用すると、命名等は不要になるメリットがあります。

この中に、クリック時の動作を記載しています。
クリックされるたびにonClickメソッドが動いてくれます。

22行目、23行目はこれまで見てきたダイアログ表示のためのコードと同じですね。

OnClickListenterのメリット・デメリット

OnClickListenterに関連する実装方法は他にも複数あります。
今回は匿名クラスを用いた方法を紹介しましたが、後々、他の実装方法も登場するかもしれません。

匿名クラスを用いた方法についてのメリットについて、以下のようなことを感じました。

・アクティビティーだけを変更すればよく、xmlを気にしないため楽
・メソッドの命名等も不要なので、比較的速く実装できる
・追加や修正、削除も結構簡単にできそう

コードのボリュームもあまり増えない印象でした。
ぱぱっと作るには丁度いいかもしれません。

次にデメリットですが、

・onClick内に複雑な処理を書くと見にくくなりそう
・実行する処理が比較的多いので、処理が重い
・命名していないので、あとで「これ何するんだっけ?」が起きそう

気を付ければあまり問題ないのかもしれませんが、ここらへんが気になった点ですね。
処理が重くなりそうなのが、一番ひっかかりますね。

結局どちらを使うべきか

onClickを使うか、OnClickListenterを使うか。
んー、その処理の目的によるとしか言えなそうですね。

個人的には、xmlにonClick属性をつける方が理解しやすいです。
しかし、ネットでは推奨していない声が多い感じでした。

上記以外にも便利なライブラリを使用して簡潔に書く方法もあるようです。
書いては反省し、書いては反省しを繰り返して改善していくしかなさそうですね。

今回は以上となります。
みなさんの参考になれば幸いです。

  • このエントリーをはてなブックマークに追加
  • LINEで送る

SNSでもご購読できます。

コメントを残す

*