指定android:onClick 属性会导致Button 实例在内部调用setOnClickListener。因此,绝对没有区别。
为了清楚了解,让我们看看框架是如何处理 XML 的onClick 属性的。
当布局文件膨胀时,其中指定的所有视图都会被实例化。在这种特定情况下,Button 实例是使用 public Button (Context context, AttributeSet attrs, int defStyle) 构造函数创建的。 XML 标记中的所有属性都从资源包中读取并作为AttributeSet 传递给构造函数。
Button 类继承自 View 类,这会导致调用 View 构造函数,该构造函数负责通过 setOnClickListener 设置点击回调处理程序。
attrs.xml 中定义的 onClick 属性在 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来调用我们Activity中定义的回调方法。
以下是其他答案中提到的问题的原因:
-
回调方法应该是公共的:由于使用了
Java Class getMethod,因此只搜索具有公共访问说明符的函数。否则准备处理IllegalAccessException 异常。
-
在 Fragment 中使用带有 onClick 的 Button 时,应在 Activity 中定义回调:
getContext().getClass().getMethod() 调用将方法搜索限制在当前上下文中,在 Fragment 的情况下为 Activity。因此方法是在 Activity 类而不是 Fragment 类中搜索的。
-
回调方法应该接受 View 参数:因为
Java Class getMethod 搜索接受 View.class 作为参数的方法。