Das Angeben von android:onClick
Attributen führt dazu, dass die Button
Instanz setOnClickListener
intern aufgerufen wird . Daher gibt es absolut keinen Unterschied.
Lassen Sie uns zum klaren Verständnis sehen, wie das XML- onClick
Attribut vom Framework behandelt wird.
Wenn eine Layoutdatei aufgeblasen wird, werden alle darin angegebenen Ansichten instanziiert. In diesem speziellen Fall wird die Button
Instanz mit dem public Button (Context context, AttributeSet attrs, int defStyle)
Konstruktor erstellt. Alle Attribute im XML-Tag werden aus dem Ressourcenpaket gelesen und an AttributeSet
den Konstruktor übergeben.
Button
Klasse wird von View
Klasse geerbt , was dazu führt, dass der View
Konstruktor 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.java
die meiste Arbeit für Sie erledigt, setOnClickListener
indem 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, setOnClickListener
wird 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 getMethod
verwendet wird, wird nur nach Funktionen mit öffentlichem Zugriffsspezifizierer gesucht. Andernfalls seien Sie bereit, IllegalAccessException
Ausnahmen 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 getMethod
nach einer Methode gesucht wird, die View.class
als Parameter akzeptiert .