Визначення android:onClick
результатів атрибута, Button
наприклад, setOnClickListener
внутрішній виклик . Отже, різниці абсолютно немає.
Щоб мати чітке розуміння, давайте подивимося, як onClick
атрибут XML обробляється рамкою.
Якщо файл макета завищений, всі представлені в ньому представлення представлені миттєво. У цьому конкретному випадку Button
екземпляр створюється за допомогою public Button (Context context, AttributeSet attrs, int defStyle)
конструктора. Усі атрибути в тезі XML зчитуються з пакета ресурсів і передаються в AttributeSet
конструктор.
Button
клас успадковується від View
класу, який призводить View
до виклику конструктора, який піклується про встановлення обробника зворотного виклику через setOnClickListener
.
Атрибут onClick, визначений у attrs.xml , в View.java згадується як R.styleable.View_onClick
.
Ось код, View.java
який робить більшу частину роботи для вас, зателефонувавши setOnClickListener
сам.
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;
Як бачите, setOnClickListener
для реєстрації зворотного дзвінка викликається, як ми це робимо в нашому коді. Різниця полягає лише в тому, що він використовується Java Reflection
для виклику методу зворотного виклику, визначеного в нашій діяльності.
Ось причина проблем, згаданих в інших відповідях:
- Метод зворотного виклику повинен бути загальнодоступним : оскільки
Java Class getMethod
він використовується, шукаються лише функції з загальнодоступним специфікатором доступу. В іншому випадку будьте готові виправити IllegalAccessException
виняток.
- Під час використання кнопки з onClick у фрагменті, зворотний виклик повинен бути визначений у розділі "Активність" :
getContext().getClass().getMethod()
виклик обмежує пошук методу поточним контекстом, який є "Активність" у разі "фрагмента". Отже, шукається метод у класі діяльності, а не у класі Fragment.
- Метод зворотного виклику повинен приймати параметр View : оскільки
Java Class getMethod
шукає метод, який приймає View.class
як параметр.