Das Angeben von android:onClickAttributen führt dazu, dass die ButtonInstanz setOnClickListenerintern aufgerufen wird . Daher gibt es absolut keinen Unterschied.
Lassen Sie uns zum klaren Verständnis sehen, wie das XML- onClickAttribut vom Framework behandelt wird.
Wenn eine Layoutdatei aufgeblasen wird, werden alle darin angegebenen Ansichten instanziiert. In diesem speziellen Fall wird die ButtonInstanz mit dem public Button (Context context, AttributeSet attrs, int defStyle)Konstruktor erstellt. Alle Attribute im XML-Tag werden aus dem Ressourcenpaket gelesen und an AttributeSetden Konstruktor übergeben.
ButtonKlasse wird von ViewKlasse geerbt , was dazu führt, dass der ViewKonstruktor aufgerufen wird, der dafür sorgt, dass der Click-Call-Back-Handler über festgelegt wird setOnClickListener.
Das Attribut onClick in definierten attrs.xml wird in View.java als bezeichnet R.styleable.View_onClick.
Hier ist der Code, der View.javadie meiste Arbeit für Sie erledigt, setOnClickListenerindem er selbst anruft .
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;
Wie Sie sehen können, setOnClickListenerwird aufgerufen, um den Rückruf zu registrieren, wie wir es in unserem Code tun. Der einzige Unterschied ist, dass es verwendetJava Reflection , dass die in unserer Aktivität definierte Rückrufmethode aufgerufen wird.
Hier sind die Gründe für Probleme, die in anderen Antworten erwähnt werden:
- Die Rückrufmethode sollte öffentlich sein : Da sie
Java Class getMethodverwendet wird, wird nur nach Funktionen mit öffentlichem Zugriffsspezifizierer gesucht. Andernfalls seien Sie bereit, IllegalAccessExceptionAusnahmen zu behandeln .
- Bei Verwendung von Button mit onClick in Fragment sollte der Rückruf unter Aktivität definiert werden :
getContext().getClass().getMethod()Aufruf beschränkt die Methodensuche auf den aktuellen Kontext, dh Aktivität bei Fragment. Daher wird die Methode innerhalb der Aktivitätsklasse und nicht innerhalb der Fragmentklasse gesucht.
- Callback-Methode sollte View-Parameter akzeptieren : Da
Java Class getMethodnach einer Methode gesucht wird, die View.classals Parameter akzeptiert .