Mając solidne doświadczenie w obszarach innych niż Java i non-Android, uczę się Androida.
Mam wiele zamieszania w różnych obszarach, jednym z nich jest obsługa kliknięć przycisków. Są na to co najmniej 4 sposoby (!!!), są one pokrótce wymienione tutaj
dla spójności wymienię je:
Miej członka
View.OnClickListener
klasy w działaniu i przypisz go do instancji, która będzie obsługiwaćonClick
logikę wonCreate
metodzie działania.Utwórz „onClickListener” w metodzie działania „onCreate” i przypisz go do przycisku za pomocą setOnClickListener
Zaimplementuj „onClickListener” w samym działaniu i przypisz „this” jako odbiornik przycisku. W przypadku, gdy aktywność ma kilka przycisków, identyfikator przycisku należy przeanalizować w celu wykonania procedury obsługi „onClick” dla odpowiedniego przycisku
Miej metodę publiczną na działaniu, które implementuje logikę `` onClick '' i przypisz ją do przycisku w deklaracji XML aktywności
Pytanie 1:
Czy to wszystkie metody, czy jest jakaś inna opcja? (Nie potrzebuję innego, po prostu ciekawy)
Dla mnie najbardziej intuicyjny byłby ten ostatni: wymaga wpisania najmniejszej ilości kodu i jest najbardziej czytelny (przynajmniej dla mnie).
Chociaż nie widzę szerokiego stosowania tego podejścia. Jakie są wady jej używania?
Pytanie 2:
Jakie są wady / zalety każdej z tych metod? Podziel się swoimi doświadczeniami lub dobrym linkiem.
Wszelkie uwagi są mile widziane!
PS Próbowałem znaleźć coś na ten temat w Google, ale jedyne co znalazłem to opis „jak” to zrobić, a nie dlaczego jest to dobre lub złe.
onCreate()
niezbyt długie wyniki. Przypisania nasłuchiwania kliknięć i klasy anonimowe można rozłożyć na oddzielną metodę pomocniczą, która jest wywoływana zonCreate()
.# 1 Często używam ostatniego, gdy mam przyciski w układzie, które nie są generowane (ale oczywiście statyczne).
Jeśli używasz go w praktyce i aplikacji biznesowej, zwróć tutaj szczególną uwagę, ponieważ podczas korzystania z zaciemniacza źródła takiego jak ProGuard, będziesz musiał zaznaczyć te metody w swojej aktywności, aby nie były zaciemniane.
Aby zarchiwizować pewnego rodzaju zabezpieczenia w czasie kompilacji przy użyciu tego podejścia, spójrz na Androida Lint ( przykład ).
# 2 Wady i zalety wszystkich metod są prawie takie same, a lekcja powinna brzmieć:
Jeśli musisz przypisać to samo
OnClickListener
do wielu instancji przycisku, zapisz go w zakresie klasy (# 1). Jeśli potrzebujesz prostego detektora dla przycisku, wykonaj anonimową implementację:button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // Take action. } });
Zwykle nie implementuję tego
OnClickListener
w działaniu, co czasami robi się trochę zagmatwane (szczególnie, gdy implementujesz wiele innych programów obsługi zdarzeń i nikt nie wie, cothis
wszystko robi).źródło
Wolę opcję 4, ale ma to dla mnie intuicyjny sens, ponieważ wykonuję zdecydowanie za dużo pracy w Grails, Groovy i JavaFX. „Magiczne” połączenia między widokiem a kontrolerem są u wszystkich wspólne. Ważne jest, aby dobrze nazwać metodę:
W widoku dodaj metodę onClick do przycisku lub innego widżetu:
android:clickable="true" android:onClick="onButtonClickCancel"
Następnie w klasie obsłuż metodę:
public void onButtonClickCancel(View view) { Toast.makeText(this, "Cancel pressed", Toast.LENGTH_LONG).show(); }
Ponownie, wyraźnie nazwij metodę, coś, co i tak powinieneś zrobić, a konserwacja stanie się drugą naturą.
Dużą zaletą jest to, że teraz możesz napisać testy jednostkowe dla metody. Opcja 1 może to zrobić, ale 2 i 3 są trudniejsze.
źródło
Najczęściej używanym sposobem jest anonimowa deklaracja
Button send = (Button) findViewById(R.id.buttonSend); send.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // handle click } });
Możesz również utworzyć obiekt View.OnClickListener i ustawić go na przycisk później, ale nadal musisz na przykład zastąpić metodę 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);
Kiedy Twoja aktywność implementuje interfejs OnClickListener, musisz przesłonić metodę onClick (View v) na poziomie aktywności. Następnie możesz przypisać tę aktywność jako odbiornik do przycisku, ponieważ już implementuje interfejs i zastępuje metodę 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) Czwarte podejście używane, gdy wiele przycisków ma tę samą procedurę obsługi i możesz zadeklarować jedną metodę w klasie aktywności i przypisać tę metodę do wielu przycisków w układzie XML, również możesz utworzyć jedną metodę dla jednego przycisku, ale w tym przypadku ja wolą deklarować procedury obsługi wewnątrz klasy aktywności.
źródło
Opcja 1 i 2 polega na użyciu klasy wewnętrznej, która spowoduje bałagan w kodzie. Opcja 2 jest trochę niechlujna, ponieważ dla każdego przycisku będzie jeden odbiornik. Jeśli masz małą liczbę przycisków, to jest w porządku. W przypadku opcji 4 myślę, że będzie to trudniejsze do debugowania, ponieważ będziesz musiał cofnąć się i czwarty kod XML i Java. Osobiście używam opcji 3, gdy muszę obsługiwać wiele kliknięć przycisków.
źródło
Moja próbka, przetestowana w Android Studio 2.1
Zdefiniuj przycisk w układzie XML
<Button android:id="@+id/btn1" android:layout_width="wrap_content" android:layout_height="wrap_content" />
Wykrywanie pulsacji 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***/ } }); }
źródło
Aby ułatwić sprawę, asp Pytanie 2 stwierdzone, możesz użyć metody lambda takiej jak ta, aby zaoszczędzić pamięć zmiennej i uniknąć poruszania się w górę iw dół w klasie widoku
//method 1 findViewById(R.id.buttonSend).setOnClickListener(v -> { // handle click });
ale jeśli chcesz od razu zastosować zdarzenie click do swojego przycisku w metodzie.
możesz skorzystać z pytania 3 autorstwa @D. Odpowiedź tran. Ale nie zapomnij zaimplementować swojej klasy widoku z
View.OnClickListener
.Innymi słowy, aby poprawnie użyć pytania nr 3
źródło
Pytanie nr 1 - to jedyny sposób obsługi kliknięć widoku.
Pytanie 2 -
Opcja nr 1 / Opcja nr 4 - Nie ma dużej różnicy między opcją nr 1 a opcją nr 4. Jedyną różnicą, jaką widzę, jest to, że w jednym przypadku działanie polega na implementacji OnClickListener, podczas gdy w drugim przypadku byłaby anonimowa implementacja.
Opcja nr 2 - W tej metodzie zostanie wygenerowana klasa anonimowa. Ta metoda jest nieco uciążliwa, ponieważ musiałbyś to zrobić wiele razy, jeśli masz wiele przycisków. W przypadku klas anonimowych musisz uważać na obsługę wycieków pamięci.
Opcja nr 3 - Chociaż jest to łatwy sposób. Zazwyczaj programiści starają się nie używać żadnej metody, dopóki jej nie napiszą, dlatego ta metoda nie jest szeroko stosowana. Można zobaczyć, że większość ludzi korzysta z opcji nr 4. Ponieważ jest czystszy pod względem kodu.
źródło
Dostępne są również opcje w postaci różnych bibliotek, które mogą sprawić, że proces ten będzie bardzo znany osobom, które używały innych frameworków MVVM.
https://developer.android.com/topic/libraries/data-binding/
Pokazuje przykład oficjalnej biblioteki, która pozwala na wiązanie przycisków w następujący sposób:
<Button android:text="Start second activity" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="@{() -> presenter.showList()}" />
źródło
Krok 1: Utwórz plik 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>
Krok 2: Utwórz 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!
źródło