Android: cara menangani klik tombol

95

Memiliki pengalaman yang solid di area non-Java dan non-Android, saya belajar Android.

Saya memiliki banyak kebingungan dengan area yang berbeda, salah satunya adalah cara menangani klik tombol. Setidaknya ada 4 cara untuk melakukan itu (!!!), semuanya tercantum secara singkat di sini

untuk tujuan konsistensi saya akan mencantumkannya:

  1. Minta anggota View.OnClickListenerkelas dalam aktivitas dan tetapkan ke instance yang akan menangani onClicklogika dalam onCreatemetode aktivitas.

  2. Buat 'onClickListener' dalam metode aktivitas 'onCreate' dan tetapkan ke tombol menggunakan setOnClickListener

  3. Implementasikan 'onClickListener' dalam aktivitas itu sendiri dan tetapkan 'ini' sebagai pemroses tombol. Untuk kasus jika aktivitas memiliki sedikit tombol, id tombol harus dianalisis untuk menjalankan pengendali 'onClick' untuk tombol yang sesuai

  4. Memiliki metode publik pada aktivitas yang mengimplementasikan logika 'onClick' dan menetapkannya ke tombol dalam deklarasi xml aktivitas

Pertanyaan 1:

Apakah itu semua metode, apakah ada pilihan lain? (Saya tidak butuh yang lain, hanya ingin tahu)

Bagi saya, cara yang paling intuitif adalah yang terbaru: cara ini membutuhkan kode paling sedikit untuk diketik dan paling mudah dibaca (setidaknya bagi saya).

Padahal, saya tidak melihat pendekatan ini digunakan secara luas. Apa kontra untuk menggunakannya?

Pertanyaan # 2:

Apa pro / kontra untuk masing-masing metode ini? Silakan bagikan pengalaman Anda atau tautan yang bagus.

Setiap umpan balik diterima!

NB Saya sudah mencoba Google dan menemukan sesuatu untuk topik ini, tetapi satu-satunya hal yang saya temukan adalah deskripsi "bagaimana" melakukan itu, bukan mengapa itu baik atau buruk.

Budda
sumber

Jawaban:

147

Pertanyaan 1: Sayangnya, yang menurut Anda paling intuitif adalah yang paling jarang digunakan di Android. Seperti yang saya pahami, Anda harus memisahkan UI (XML) dan fungsionalitas komputasi (Java Class Files). Itu juga membuat debugging lebih mudah. Sebenarnya jauh lebih mudah untuk membaca dengan cara ini dan memikirkan tentang Android imo.

Pertanyaan 2: Saya yakin dua yang paling sering digunakan adalah # 2 dan # 3. Saya akan menggunakan tombol clickButton sebagai contoh.

2

dalam bentuk kelas anonim.

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***
            }
        });

Ini adalah favorit saya karena memiliki metode onClick tepat di sebelah tempat variabel tombol disetel dengan findViewById. Tampaknya sangat rapi dan rapi bahwa semua yang berhubungan dengan Tampilan Tombol ClickButton ini ada di sini.

Penipu yang dikomentari oleh rekan kerja saya, adalah membayangkan Anda memiliki banyak tampilan yang membutuhkan pendengar klik. Anda dapat melihat bahwa onCreate Anda akan menjadi sangat panjang. Karena itulah dia suka menggunakan:

3

Katakanlah Anda punya, 5 clickButtons:

Pastikan Aktivitas / Fragmen Anda menerapkan 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
    }
}

Cara ini, seperti yang dijelaskan rekan kerja saya, lebih rapi di matanya, karena semua komputasi onClick ditangani di satu tempat dan tidak memenuhi metode onCreate. Tapi sisi negatifnya yang saya lihat adalah, bahwa:

  1. melihat diri mereka sendiri,
  2. dan objek lain apa pun yang mungkin terletak di onCreate yang digunakan oleh metode onClick harus dibuat menjadi bidang.

Beri tahu saya jika Anda ingin informasi lebih lanjut. Saya tidak menjawab pertanyaan Anda sepenuhnya karena itu pertanyaan yang cukup panjang. Dan jika saya menemukan beberapa situs, saya akan memperluas jawaban saya, sekarang saya hanya memberikan sedikit pengalaman.

dumamilk
sumber
1
Untuk opsi 2 Anda pasti ingin membuatnya: clickButton.setOnClickListener (new View.OnClickListener () {@Override public void onClick (View v) {// TODO what you want to do}}); untuk membantunya menyelesaikan OnClickListener
ColossalChris
Opsi 3 mungkin yang paling bersih dan termudah untuk dikembangkan dengan pola MVP.
Raffaeu
Opsi 2 masih bisa menghasilkan onCreate()yang tidak terlalu lama. Tugas pendengar klik dan kelas anonim dapat difaktorkan menjadi metode helper terpisah yang dipanggil dari onCreate().
Nick Alexeev
@Colossal: Anda tidak harus melakukannya. Tambahkan ekstensi ke Kelas Aktivitas seperti "implements View.OnClickListener".
TomeeNS
10

# 1 Saya sering menggunakan yang terakhir ketika memiliki tombol pada tata letak yang tidak dihasilkan (tetapi jelas statis).

Jika Anda menggunakannya dalam praktik dan dalam aplikasi bisnis, berikan perhatian ekstra di sini, karena saat Anda menggunakan obfuscater sumber seperti ProGuard, Anda harus menandai metode ini dalam aktivitas Anda agar tidak dikaburkan.

Untuk mengarsipkan beberapa jenis kompilasi-waktu-keamanan dengan pendekatan ini, lihat Android Lint ( contoh ).


# 2 Pro dan kontra untuk semua metode hampir sama dan pelajarannya harus:

Gunakan apa pun yang paling sesuai atau terasa paling intuitif bagi Anda.

Jika Anda harus menetapkan hal yang sama OnClickListenerke beberapa instance tombol, simpan di class-scope (# 1). Jika Anda membutuhkan listener sederhana untuk sebuah Button, lakukan implementasi anonim:

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

Saya cenderung tidak mengimplementasikan OnClickListenerdalam aktivitas, ini menjadi sedikit membingungkan dari waktu ke waktu (terutama ketika Anda mengimplementasikan beberapa event-handler lain dan tidak ada yang tahu apa thisyang dilakukan semua).

Lukas Knuth
sumber
Saya mengikuti hal yang sama tetapi masih tidak mendapatkan keluaran untuk fungsi, kode dan kueri saya ada di sini: stackoverflow.com/questions/25107427/…
Rocket
8

Saya lebih suka opsi 4, tetapi itu masuk akal bagi saya karena saya melakukan terlalu banyak pekerjaan di Grails, Groovy, dan JavaFX. Koneksi "ajaib" antara tampilan dan pengontrol adalah umum di semua. Penting untuk memberi nama metode dengan baik:

Dalam tampilan, tambahkan metode onClick ke tombol atau widget lain:

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

Kemudian di kelas, tangani metode tersebut:

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

Sekali lagi, sebutkan metodenya dengan jelas, sesuatu yang harus Anda lakukan, dan pemeliharaan menjadi kebiasaan.

Satu keuntungan besar adalah Anda dapat menulis pengujian unit sekarang untuk metode tersebut. Opsi 1 dapat melakukan ini, tetapi opsi 2 dan 3 lebih sulit.

Steve Gelman
sumber
1
Saya akan mengoceh sedikit dan menyarankan opsi kelima (tidak, tidak dibintangi oleh Bruce Willis :)), varian dari opsi 2: gunakan kelas Presenter dalam kerangka Model-View-Presenter untuk menangani klik. Itu membuat pengujian otomatis JAUH lebih mudah. Lihat tautan ini untuk informasi yang lebih baik: codelabs.developers.google.com/codelabs/android-testing/…
Steve Gelman
4

Cara yang paling sering digunakan adalah, deklarasi anonim

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

Anda juga dapat membuat objek View.OnClickListener dan menyetelnya ke tombol nanti, tetapi Anda masih perlu mengganti metode onClick misalnya

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

Saat aktivitas Anda mengimplementasikan antarmuka OnClickListener, Anda harus mengganti metode onClick (View v) pada tingkat aktivitas. Kemudian Anda bisa menganggap aktivitas ini sebagai tombol pemroses, karena ini sudah mengimplementasikan antarmuka dan mengganti metode 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) Pendekatan ke-4 digunakan ketika beberapa tombol memiliki penangan yang sama, dan Anda dapat mendeklarasikan satu metode dalam kelas aktivitas dan menetapkan metode ini ke beberapa tombol dalam tata letak xml, Anda juga dapat membuat satu metode untuk satu tombol, tetapi dalam kasus ini saya lebih memilih untuk mendeklarasikan penangan di dalam kelas aktivitas.

Georgy Gobozov
sumber
1

Opsi 1 dan 2 melibatkan penggunaan kelas dalam yang akan membuat kode menjadi berantakan. Opsi 2 agak berantakan karena hanya akan ada satu pendengar untuk setiap tombol. Jika Anda memiliki sejumlah kecil tombol, ini tidak masalah. Untuk opsi 4 saya pikir ini akan lebih sulit untuk di-debug karena Anda harus kembali dan keempat kode xml dan java. Saya pribadi menggunakan opsi 3 ketika saya harus menangani beberapa klik tombol.

CChi
sumber
1

Sampel saya, Diuji di Android studio 2.1

Tombol Tentukan dalam tata letak xml

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

Deteksi denyut Jawa

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***/
        }
    });
}
Webserveis
sumber
1

Untuk mempermudah pernyataan asp Pertanyaan 2, Anda dapat menggunakan metode lambda seperti ini untuk menghemat memori variabel dan untuk menghindari navigasi ke atas dan ke bawah dalam kelas tampilan Anda

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

tetapi jika Anda ingin menerapkan acara klik ke tombol Anda sekaligus dalam suatu metode.

Anda dapat menggunakan Pertanyaan 3 oleh @D. Tran menjawab. Tapi jangan lupa untuk mengimplementasikan kelas tampilan Anda dengan View.OnClickListener.

Selain itu, gunakan Pertanyaan # 3 dengan benar

Michael
sumber
1
Ini harus dianggap sebagai jawaban modern yang dikombinasikan dengan referensi metode IMO. Sebagian besar jawaban lain tidak menyebutkan fakta bahwa mereka adalah kode Java8 pra-lama di Android.
Ryan The Leach
0

Pertanyaan # 1 - Ini adalah satu-satunya cara untuk menangani klik tampilan.

Pertanyaan # 2 -
Opsi # 1 / Opsi # 4 - Tidak banyak perbedaan antara opsi # 1 dan opsi # 4. Satu-satunya perbedaan yang saya lihat adalah dalam satu kasus aktivitas mengimplementasikan OnClickListener, sedangkan, di kasus lain, akan ada implementasi anonim.

Opsi # 2 - Dalam metode ini kelas anonim akan dibuat. Metode ini agak rumit, karena Anda harus melakukannya beberapa kali, jika Anda memiliki banyak tombol. Untuk kelas Anonymous, Anda harus berhati-hati dalam menangani kebocoran memori.

Opsi # 3 - Padahal, ini cara yang mudah. Biasanya, Pemrogram mencoba untuk tidak menggunakan metode apa pun sampai mereka menulisnya, dan karenanya metode ini tidak digunakan secara luas. Anda akan melihat kebanyakan orang menggunakan Opsi # 4. Karena lebih bersih dari segi kode.

Gaurav Arora
sumber
Hai Gaurav, terima kasih atas jawabannya. Tapi bisakah Anda menjelaskan apa yang Anda maksud di sini: Untuk kelas Anonymous, Anda harus berhati-hati dalam menangani kebocoran memori. Bagaimana kebocoran memori bisa terjadi di sini?
Budda
Anda hanya perlu menyadari bahwa: jika Anda membuat kelas anonim di dalam metode yang mungkin dipanggil beberapa kali selama masa pakai aplikasi Anda, tidak beberapa instance dari satu kelas akan dibuat, tetapi beberapa kelas termasuk instance-nya. Anda dapat menghindarinya dengan menggunakan kelas dalam biasa dan membuat instance listener sebagai kolom instance. Cobalah untuk mengurangi kelas listener yang berbeda dengan membuat status listener menjadi sadar melalui argumen konstruktor. Kelas dalam reguler memberi Anda manfaat dari konstruktor khusus dan metode lainnya.
Risadinha
0

Ada juga opsi yang tersedia dalam bentuk berbagai pustaka yang dapat membuat proses ini sangat familier bagi orang-orang yang telah menggunakan kerangka kerja MVVM lainnya.

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

Menunjukkan contoh perpustakaan resmi, yang memungkinkan Anda untuk mengikat tombol seperti ini:

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

Langkah 1: Buat File 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>

Langkah 2: Buat 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!

Manikanta Reddy
sumber