Podanie android:onClick
atrybutu powoduje wewnętrzne Button
wywołanie instancji setOnClickListener
. Dlatego nie ma absolutnie żadnej różnicy.
Aby mieć wyraźne zrozumienie, zobaczmy, jak środowisko XML onClick
obsługuje atrybut.
Podczas nadmuchiwania pliku układu tworzone są wszystkie określone w nim widoki. W tym konkretnym przypadku Button
instancja jest tworzona za pomocą public Button (Context context, AttributeSet attrs, int defStyle)
konstruktora. Wszystkie atrybuty w znaczniku XML są odczytywane z pakietu zasobów i przekazywane AttributeSet
do konstruktora.
Button
klasa jest dziedziczona z View
klasy, co powoduje View
wywołanie konstruktora, który dba o ustawienie funkcji obsługi wywołania zwrotnego za pośrednictwem setOnClickListener
.
Atrybut onClick zdefiniowany w pliku attrs.xml jest nazywany w View.java jako R.styleable.View_onClick
.
Oto kod, View.java
który wykonuje większość pracy dla Ciebie, dzwoniąc setOnClickListener
sam.
case R.styleable.View_onClick:
if (context.isRestricted()) {
throw new IllegalStateException("The android:onClick attribute cannot "
+ "be used within a restricted context");
}
final String handlerName = a.getString(attr);
if (handlerName != null) {
setOnClickListener(new OnClickListener() {
private Method mHandler;
public void onClick(View v) {
if (mHandler == null) {
try {
mHandler = getContext().getClass().getMethod(handlerName,
View.class);
} catch (NoSuchMethodException e) {
int id = getId();
String idText = id == NO_ID ? "" : " with id '"
+ getContext().getResources().getResourceEntryName(
id) + "'";
throw new IllegalStateException("Could not find a method " +
handlerName + "(View) in the activity "
+ getContext().getClass() + " for onClick handler"
+ " on view " + View.this.getClass() + idText, e);
}
}
try {
mHandler.invoke(getContext(), View.this);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Could not execute non "
+ "public method of the activity", e);
} catch (InvocationTargetException e) {
throw new IllegalStateException("Could not execute "
+ "method of the activity", e);
}
}
});
}
break;
Jak widać, setOnClickListener
jest wywoływany w celu zarejestrowania oddzwaniania, tak jak robimy to w naszym kodzie. Jedyną różnicą jest to, że używa Java Reflection
metody wywołania zwrotnego zdefiniowanej w naszym działaniu.
Oto powód problemów wymienionych w innych odpowiedziach:
- Metoda wywołania zwrotnego powinna być publiczna : ponieważ
Java Class getMethod
jest używana, wyszukiwane są tylko funkcje ze specyfikatorem publicznego dostępu. W przeciwnym razie przygotuj się na IllegalAccessException
wyjątek.
- Podczas korzystania z przycisku z onClick we fragmencie, wywołanie zwrotne powinno być zdefiniowane w Activity :
getContext().getClass().getMethod()
call ogranicza wyszukiwanie metod do bieżącego kontekstu, którym jest Activity w przypadku Fragmentu. Dlatego metoda jest przeszukiwana w obrębie klasy Activity, a nie klasy Fragment.
- Metoda wywołania zwrotnego powinna zaakceptować Wyświetl parametr : Ponieważ
Java Class getMethod
wyszukuje metodę, która przyjmuje View.class
jako parametr.