指定android:onClick属性会导致Button实例在内部调用setOnClickListener。因此两者绝对没有区别。
为了更清楚地理解,让我们看看框架是如何处理XML onClick属性的。
当布局文件被膨胀时,其中指定的所有视图都会被实例化。在这个特定的情况下,Button实例是使用公共Button (Context Context, AttributeSet attrs, int defStyle)构造函数创建的。XML标记中的所有属性都是从资源包中读取的,并作为AttributeSet传递给构造函数。
Button类继承自View类,它导致View构造函数被调用,View构造函数通过setOnClickListener负责设置点击回调处理程序。
在attrs.xml中定义的onClick属性在View.java中被引用为r.s eleable . 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来调用Activity中定义的回调方法。
以下是其他回答中提到的问题的原因:
Callback method should be public : Since Java Class getMethod is used, only functions with public access specifier are searched for. Otherwise be ready to handle IllegalAccessException exception.
While using Button with onClick in Fragment, the callback should be defined in Activity : getContext().getClass().getMethod() call restricts the method search to the current context, which is Activity in case of Fragment. Hence method is searched within Activity class and not Fragment class.
Callback method should accept View parameter : Since Java Class getMethod searches for method which accepts View.class as parameter.