Se si specifica l' android:onClick
attributo, l' Button
istanza si chiama setOnClickListener
internamente Quindi non c'è assolutamente alcuna differenza.
Per avere una chiara comprensione, vediamo come onClick
viene gestito l'attributo XML dal framework.
Quando un file di layout viene gonfiato, vengono istanziate tutte le viste specificate in esso. In questo caso specifico, l' Button
istanza viene creata utilizzando il public Button (Context context, AttributeSet attrs, int defStyle)
costruttore. Tutti gli attributi nel tag XML vengono letti dal pacchetto di risorse e passati AttributeSet
al costruttore.
Button
La classe viene ereditata dalla View
classe che risulta nella View
chiamata del costruttore, che si occupa di impostare il gestore di richiamata click via setOnClickListener
.
L'attributo onClick definito in attrs.xml è indicato in View.java come R.styleable.View_onClick
.
Ecco il codice View.java
che fa la maggior parte del lavoro per te chiamando setOnClickListener
da solo.
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;
Come puoi vedere, setOnClickListener
viene chiamato per registrare il callback, come facciamo nel nostro codice. L'unica differenza è che utilizza Java Reflection
per invocare il metodo di callback definito nella nostra Attività.
Ecco il motivo dei problemi menzionati in altre risposte:
- Il metodo di callback dovrebbe essere pubblico : poiché
Java Class getMethod
viene utilizzato, vengono cercate solo le funzioni con identificatore di accesso pubblico. Altrimenti sii pronto a gestire l' IllegalAccessException
eccezione.
- Mentre si utilizza Button con onClick in Fragment, il callback deve essere definito in Activity :
getContext().getClass().getMethod()
call limita la ricerca del metodo al contesto corrente, che è Activity in caso di Fragment. Quindi il metodo viene cercato all'interno della classe Activity e non nella classe Fragment.
- Il metodo di callback dovrebbe accettare Visualizza parametro : Poiché
Java Class getMethod
cerca un metodo che accetta View.class
come parametro.