การระบุandroid:onClick
ผลลัพธ์แอ็ตทริบิวต์ในการButton
โทรsetOnClickListener
ภายใน ดังนั้นจึงไม่มีความแตกต่างอย่างแน่นอน
หากต้องการความเข้าใจที่ชัดเจนให้เราดูว่าonClick
มีการจัดการแอตทริบิวต์XML โดยกรอบงานอย่างไร
เมื่อไฟล์เลย์เอาต์ถูกขยายมุมมองทั้งหมดที่ระบุในนั้นจะถูกสร้างอินสแตนซ์ ในกรณีเฉพาะนี้Button
อินสแตนซ์ถูกสร้างขึ้นโดยใช้ตัวpublic Button (Context context, AttributeSet attrs, int defStyle)
สร้าง แอ็ตทริบิวต์ทั้งหมดในแท็ก XML ถูกอ่านจากบันเดิลรีซอร์สและส่งผ่านAttributeSet
ไปยังตัวสร้าง
Button
class ได้รับการสืบทอดจากView
คลาสซึ่งส่งผลให้ตัวView
สร้างถูกเรียกใช้ซึ่งดูแลการตั้งค่า call call handler กลับมาทาง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 in Fragment การโทรกลับควรถูกกำหนดในกิจกรรม : การ
getContext().getClass().getMethod()
โทรจะ จำกัด การค้นหาวิธีการตามบริบทปัจจุบันซึ่งเป็นกิจกรรมในกรณีของส่วน ดังนั้นวิธีการค้นหาภายในชั้นเรียนกิจกรรมและไม่ได้ชั้นส่วน
- วิธีการโทรกลับควรยอมรับพารามิเตอร์ดู : เนื่องจาก
Java Class getMethod
ค้นหาวิธีที่ยอมรับView.class
เป็นพารามิเตอร์