A especificação de android:onClick
resultados de atributos na Button
instância que chama setOnClickListener
internamente. Portanto, não há absolutamente nenhuma diferença.
Para ter um entendimento claro, vamos ver como o onClick
atributo XML é tratado pela estrutura.
Quando um arquivo de layout é inflado, todas as Visualizações especificadas nele são instanciadas. Nesse caso específico, a Button
instância é criada usando o public Button (Context context, AttributeSet attrs, int defStyle)
construtor. Todos os atributos na tag XML são lidos no pacote de recursos e transmitidos AttributeSet
para o construtor.
Button
A classe é herdada da View
classe que resulta na View
chamada do construtor, que cuida da configuração do manipulador de retorno de chamada por clique setOnClickListener
.
O atributo onClick definido em attrs.xml , é referido em View.java como R.styleable.View_onClick
.
Aqui está o código View.java
que faz a maior parte do trabalho para você chamando setOnClickListener
por si só.
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;
Como você pode ver, setOnClickListener
é chamado para registrar o retorno de chamada, como fazemos em nosso código. A única diferença que ele usa Java Reflection
para chamar o método de retorno de chamada definido em nossa Atividade.
Aqui está o motivo dos problemas mencionados em outras respostas:
- O método de retorno de chamada deve ser público : como
Java Class getMethod
é usado, apenas as funções com especificador de acesso público são pesquisadas. Caso contrário, esteja pronto para lidar com a IllegalAccessException
exceção.
- Ao usar o botão com onClick no fragmento, o retorno de chamada deve ser definido em Activity :
getContext().getClass().getMethod()
call restringe a pesquisa do método ao contexto atual, que é Activity no caso de Fragment. Portanto, o método é pesquisado na classe Activity e não na classe Fragment.
- O método de retorno de chamada deve aceitar o parâmetro View : uma vez que
Java Class getMethod
procura o método que aceita View.class
como parâmetro.