Se si specifica l' android:onClickattributo, l' Buttonistanza si chiama setOnClickListenerinternamente Quindi non c'è assolutamente alcuna differenza.
Per avere una chiara comprensione, vediamo come onClickviene 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' Buttonistanza 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 AttributeSetal costruttore.
ButtonLa classe viene ereditata dalla Viewclasse che risulta nella Viewchiamata 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.javache fa la maggior parte del lavoro per te chiamando setOnClickListenerda 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, setOnClickListenerviene chiamato per registrare il callback, come facciamo nel nostro codice. L'unica differenza è che utilizza Java Reflectionper 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 getMethodviene utilizzato, vengono cercate solo le funzioni con identificatore di accesso pubblico. Altrimenti sii pronto a gestire l' IllegalAccessExceptioneccezione.
- 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 getMethodcerca un metodo che accetta View.classcome parametro.