Android:ボタンクリックの処理方法


95

JavaやAndroid以外の分野で確かな経験を積んでいる私は、Androidを学んでいます。

私はさまざまな分野で多くの混乱を抱えていますが、その1つはボタンのクリックの処理方法です。(!!!)、彼らは簡単に表示されていることをやって、少なくとも4の方法があり、ここでは、

一貫性を保つために、それらをリストします。

  1. View.OnClickListenerアクティビティにクラスのメンバーを入れonClickonCreateアクティビティメソッドのロジックを処理するインスタンスに割り当てます。

  2. 「onCreate」アクティビティメソッドで「onClickListener」を作成し、setOnClickListenerを使用してボタンに割り当てます

  3. アクティビティ自体に「onClickListener」を実装し、ボタンのリスナーとして「this」を割り当てます。アクティビティにボタンが少ない場合は、ボタンIDを分析して、適切なボタンの「onClick」ハンドラを実行する必要があります

  4. 'onClick'ロジックを実装するアクティビティにパブリックメソッドを用意し、それをアクティビティxml宣言のボタンに割り当てます。

質問1:

それらはすべてメソッドですか、他のオプションはありますか?(私は他に必要はありません、好奇心が強いだけです)

私にとって、最も直感的な方法は最新の方法です。これは、入力する必要のあるコードの量が最も少なく、最も読みやすい(少なくとも私にとって)方法です。

ただし、このアプローチが広く使用されているとは思いません。それを使用することの短所は何ですか?

質問2:

これらの各方法の長所と短所は何ですか?あなたの経験または良いリンクを共有してください。

どんなフィードバックでも大歓迎です!

PS私はGoogleでこのトピックの何かを見つけようとしましたが、私が見つけた唯一のことは、それを行う方法の説明であり、なぜそれが良いか悪いかではありません。

回答:


147

質問1:残念ながら、あなたが最も直感的に言っているのは、Androidで最も使用されていないものです。私が理解しているように、UI(XML)と計算機能(Java Class Files)を分離する必要があります。また、デバッグが容易になります。この方法を読んでAndroid imoについて考えるのは、実際にははるかに簡単です。

質問2:主に使用される2つは#2と#3だと思います。例として、ボタンのclickButtonを使用します。

2

匿名クラスの形式です。

Button clickButton = (Button) findViewById(R.id.clickButton);
clickButton.setOnClickListener( new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                ***Do what you want with the click here***
            }
        });

これは、ボタン変数がfindViewByIdで設定された場所のすぐ隣にonClickメソッドがあるため、私のお気に入りです。このclickButtonボタンビューを処理するすべてのものがここに配置されていることは、非常に整然としているようです。

私の同僚がコメントしている短所は、あなたがonclickリスナーを必要とする多くのビューを持っていると想像することです。onCreateが非常に長くなることがわかります。だから彼が使うのが好きな理由:

5つのclickButtonがあるとします。

アクティビティ/フラグメントがOnClickListenerを実装していることを確認してください

// in OnCreate

Button mClickButton1 = (Button)findViewById(R.id.clickButton1);
mClickButton1.setOnClickListener(this);
Button mClickButton2 = (Button)findViewById(R.id.clickButton2);
mClickButton2.setOnClickListener(this);
Button mClickButton3 = (Button)findViewById(R.id.clickButton3);
mClickButton3.setOnClickListener(this);
Button mClickButton4 = (Button)findViewById(R.id.clickButton4);
mClickButton4.setOnClickListener(this);
Button mClickButton5 = (Button)findViewById(R.id.clickButton5);
mClickButton5.setOnClickListener(this);


// somewhere else in your code

public void onClick(View v) {
    switch (v.getId()) {
        case  R.id.clickButton1: {
            // do something for button 1 click
            break;
        }

        case R.id.clickButton2: {
            // do something for button 2 click
            break;
        }

        //.... etc
    }
}

私の同僚が説明するこの方法は、すべてのonClick計算が1か所で処理され、onCreateメソッドを混雑させないため、彼の目にはすっきりしています。しかし、私が目にする欠点は、次のことです。

  1. 自分自身を表示し、
  2. また、onClickメソッドで使用されるonCreateにあるその他のオブジェクトは、フィールドにする必要があります。

さらに情報が必要な場合はお知らせください。長い質問なので、完全には答えられませんでした。そして、もし私がいくつかのサイトを見つけたら、私は私の答えを拡大します、今、私はいくつかの経験を与えています。


1
オプション2の場合、次のようにします。OnClickListenerの解決を支援する
ColossalChris

オプション3は、MVPパターンで拡張するのがおそらく最もクリーンで最も簡単です。
Raffaeu

オプション2でも、onCreate()それほど長くはありません。クリックリスナーの割り当てと匿名クラスは、から呼び出される個別のヘルパーメソッドに分解できますonCreate()
Nick Alexeev 2016

@Colossal:あなたはそれをする必要はありません。「implements View.OnClickListener」のような拡張機能をアクティビティクラスに追加します。
TomeeNS 2018年

10

#1生成されない(ただし静的な)レイアウトのボタンがある場合、最後のボタンを頻繁に使用します。

実際に使用する場合やビジネスアプリケーションで使用する場合は、ここで特に注意してください。ProGuardのようなソース難読化ツールを使用する場合は、アクティビティでこれらのメソッドを難読化しないようにマークする必要があるためです。

このアプローチである種のコンパイル時セキュリティをアーカイブするには、Android Lint)をご覧ください。


#2 すべての方法の長所と短所はほとんど同じであり、レッスンは次のようになります。

これまでで最も適切であるか、最も直感的に感じるものを使用してください。

同じものOnClickListenerを複数のボタンインスタンスに割り当てる必要がある場合は、クラススコープ(#1)に保存します。Buttonの単純なリスナーが必要な場合は、匿名の実装を作成します。

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        // Take action.
    }
});

私はOnClickListenerアクティビティにを実装しない傾向があり、これは時々少し混乱します(特に、他の複数のイベントハンドラーを実装し、誰もが何thisをしているのか誰も知らない場合)。


同じことを行っていますが、関数の出力がまだありません。コードとクエリは次のとおりです。stackoverflow.com
Rocket

8

私はオプション4を好みますが、Grails、Groovy、JavaFXであまりにも多くの作業を行うため、直感的に理解できます。ビューとコントローラーの間の「マジック」接続は、すべてに共通です。メソッドに適切な名前を付けることが重要です。

ビューで、ボタンまたは他のウィジェットにonClickメソッドを追加します。

    android:clickable="true"
    android:onClick="onButtonClickCancel"

次に、クラスでメソッドを処理します。

public void onButtonClickCancel(View view) {
    Toast.makeText(this, "Cancel pressed", Toast.LENGTH_LONG).show();
}

繰り返しになりますが、メソッドには明確に名前を付けてください。とにかくやるべきことを行うと、メンテナンスは自然なものになります。

大きな利点の1つは、メソッドの単体テストを今すぐ作成できることです。オプション1はこれを行うことができますが、2と3はより困難です。


1
私は少しワッフルして5番目のオプションを提案します(いいえ、ブルースウィリスに出演しないでください:))、オプションのバリアント2:モデルビュープレゼンターフレームワークでプレゼンタークラスを使用してクリックを処理します。自動テストがはるかに簡単になります。詳細については、このリンクを確認してください:codelabs.developers.google.com/codelabs/android-testing/…–
Steve Gelman

4

最も使用される方法は、匿名の宣言です

    Button send = (Button) findViewById(R.id.buttonSend);
    send.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // handle click
        }
    });

また、View.OnClickListenerオブジェクトを作成して後でボタンに設定することもできますが、たとえばonClickメソッドをオーバーライドする必要があります。

View.OnClickListener listener = new View.OnClickListener(){
     @Override
        public void onClick(View v) {
            // handle click
        }
}   
Button send = (Button) findViewById(R.id.buttonSend);
send.setOnClickListener(listener);

アクティビティがOnClickListenerインターフェースを実装する場合、アクティビティレベルでonClick(View v)メソッドをオーバーライドする必要があります。次に、このアクティビティをボタンのリスナーとしてアサートできます。これは、インターフェースを実装していて、onClick()メソッドをオーバーライドしているためです。

public class MyActivity extends Activity implements View.OnClickListener{


    @Override
    public void onClick(View v) {
        // handle click
    }


    @Override
    public void onCreate(Bundle b) {
        Button send = (Button) findViewById(R.id.buttonSend);
        send.setOnClickListener(this);
    }

}

(imho)複数のボタンに同じハンドラーがある場合に使用される4番目のアプローチで、アクティビティクラスで1つのメソッドを宣言し、このメソッドをxmlレイアウトの複数のボタンに割り当てることができます。また、この場合、1つのボタンに対して1つのメソッドを作成できます。アクティビティクラス内でハンドラーを宣言することを好む。


1

オプション1と2では、コードをわかりやすくする内部クラスを使用します。オプション2は、すべてのボタンに1つのリスナーがあるため、面倒です。ボタンの数が少ない場合は問題ありません。オプション4の場合、XMLコードとJavaコードに戻って4番目に戻る必要があるため、これはデバッグが難しいと思います。複数のボタンクリックを処理する必要がある場合は、個人的にオプション3を使用します。


1

私のサンプル、Android Studio 2.1でテスト済み

XMLレイアウトでボタンを定義する

<Button
    android:id="@+id/btn1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

Java脈動検出

Button clickButton = (Button) findViewById(R.id.btn1);
if (clickButton != null) {
    clickButton.setOnClickListener( new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            /***Do what you want with the click here***/
        }
    });
}

1

質問2で述べたように物事を簡単にするために、このようなラムダメソッドを使用して変数のメモリを節約し、ビュークラス内を上下に移動しないようにすることができます。

//method 1
findViewById(R.id.buttonSend).setOnClickListener(v -> {
          // handle click
});

しかし、メソッドでボタンにクリックイベントを一度に適用したい場合。

@Dの質問3を利用できます。トランの答え。ただし、でビュークラスを実装することを忘れないでくださいView.OnClickListener

他の質問3を適切に使用するには


1
これは、メソッド参照IMOと組み合わせた最新の回答と見なす必要があります。他のほとんどの回答は、それらがAndroid上のJava8より前の古いコードであるという事実を明らかにしていません。
Ryan The Leach

0

質問1-これらは、ビューのクリックを処理する唯一の方法です。

質問2-
オプション1 /オプション4-オプション1とオプション4の間に大きな違いはありません。私が目にする唯一の違いは、1つのケースではアクティビティがOnClickListenerを実装することですが、もう1つのケースでは、匿名の実装があります。

オプション2-このメソッドでは、匿名クラスが生成されます。複数のボタンがある場合、この方法は複数回行う必要があるため、少し面倒です。匿名クラスの場合、メモリリークの処理に注意する必要があります。

オプション#3-ただし、これは簡単な方法です。通常、プログラマーはそれを書くまでメソッドを使用しないようにします。そのため、このメソッドは広く使用されていません。ほとんどの人がOption#4を使用しているのがわかります。コードの点でよりクリーンだからです。


こんにちはガウラフ、答えてくれてありがとう しかし、ここで何を意味するのかを明確にしていただけますか?匿名クラスの場合、メモリリークの処理に注意する必要があります。ここでメモリリークはどのように発生しますか?
Budda 2013

アプリの存続期間中に複数回呼び出される可能性のあるメソッド内に匿名クラスを作成すると、1つのクラスのインスタンスが複数作成されるのではなく、それらのインスタンスを含む複数のクラスが作成されます。これは、通常の内部クラスを使用して、リスナーをインスタンスフィールドとしてインスタンス化することで回避できます。コンストラクターの引数を介してリスナーの状態を認識させることにより、さまざまなリスナークラスを減らしてみてください。通常の内部クラスは、カスタムコンストラクターやその他のメソッドの利点を提供します。
Risadinha 2013年

0

他のMVVMフレームワークを使用したことがあるユーザーにとって、このプロセスを非常に使い慣れたものにすることができるさまざまなライブラリの形式で利用可能なオプションもあります。

https://developer.android.com/topic/libraries/data-binding/

次のようなボタンをバインドできる公式ライブラリの例を示します。

<Button
    android:text="Start second activity"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:onClick="@{() -> presenter.showList()}"
/>

0

ステップ1:XMLファイルを作成します。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/btnClickEvent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Click Me" />
</LinearLayout>

ステップ2:MainActivityを作成します。

package com.scancode.acutesoft.telephonymanagerapp;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends Activity implements View.OnClickListener {

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

        btnClickEvent = (Button) findViewById(R.id.btnClickEvent);
        btnClickEvent.setOnClickListener(MainActivity.this);

    }

    @Override
    public void onClick(View v) {
        //Your Logic
    }
}

HappyCoding!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.