나는 당신이 onClick
두 가지 방법으로 버튼에 핸들러를 할당 할 수 있다는 것을 읽었습니다 .
android:onClick
서명과 함께 공용 메소드의 이름을 사용하는 XML 속성 void name(View v)
을 사용하거나 인터페이스 setOnClickListener
를 구현하는 오브젝트를 전달하는 메소드 를 사용하십시오 OnClickListener
. 후자는 종종 개인적으로 좋아하지 않는 (개인 취향) 또는을 구현하는 내부 클래스를 정의하는 익명 클래스가 필요합니다 OnClickListener
.
XML 속성을 사용하면 클래스 대신 메소드를 정의하면되므로 XML 레이아웃이 아닌 코드를 통해 동일한 작업을 수행 할 수 있는지 궁금합니다.
답변
아니요, 코드로는 불가능합니다. 속성 OnClickListener
을 정의 할 때 Android가 자동으로 구현 android:onClick="someMethod"
합니다.
이 두 코드 스 니펫은 동일하며 두 가지 다른 방식으로 구현됩니다.
코드 구현
Button btn = (Button) findViewById(R.id.mybutton);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
myFancyMethod(v);
}
});
// some more code
public void myFancyMethod(View v) {
// does something very interesting
}
위의 코드 구현은입니다 OnClickListener
. 그리고 이것은 XML 구현입니다.
XML 구현
<?xml version="1.0" encoding="utf-8"?>
<!-- layout elements -->
<Button android:id="@+id/mybutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click me!"
android:onClick="myFancyMethod" />
<!-- even more layout elements -->
백그라운드에서 Android는 Java 코드 외에 다른 방법으로 click 이벤트에서 메소드를 호출합니다.
위의 XML을 사용하면 Android는 현재 활동에서만 onClick
메소드를 찾습니다 myFancyMethod()
. 프래그먼트를 사용하여 XML을 추가하더라도 Android는 XML을 추가하는 데 사용되는 프래그먼트 파일 에서 onClick
메소드를 찾지 않으므로 .java
프래그먼트를 사용하는 경우 기억해야합니다.
또 다른 중요한 점을 발견했습니다. 익명의 방법을 선호하지 않는다고 언급했습니다 . 익명 클래스 를 좋아하지 않는다고 말하려고했습니다 .
답변
최고의 답변을 보았을 때 내 문제가 멋진 메소드에 매개 변수 (View v)를 넣지 않았다는 것을 깨달았습니다.
public void myFancyMethod(View v) {}
XML에서 액세스하려고 할 때
android:onClick="myFancyMethod"/>
누군가에게 도움이되기를 바랍니다.
답변
android:onClick
는 API 수준 4 이상을위한 것이므로 <1.6을 타겟팅하는 경우 사용할 수 없습니다.
답변
메소드를 공개하는 것을 잊었는지 확인하십시오!
답변
android:onClick
속성을 지정 하면 Button
인스턴스가 setOnClickListener
내부적으로 호출 됩니다. 따라서 아무런 차이가 없습니다.
명확한 이해 onClick
를 위해 프레임 워크가 XML 속성을 처리 하는 방법을 살펴 보겠습니다 .
배치 파일이 팽창되면 여기에 지정된 모든 뷰가 인스턴스화됩니다. 이 경우 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
우리의 활동에 정의 된 콜백 메소드를 호출하는 데 사용 한다는 점만 다릅니다 .
다른 답변에서 언급 된 문제의 이유는 다음과 같습니다.
- 콜백 방법은 공개한다 : 이후
Java Class getMethod
를 검색 지정자 공용 액세스 사용 만 기능한다. 그렇지 않으면IllegalAccessException
예외 를 처리 할 준비가됩니다 . - Fragment에서 onClick과 함께 Button을 사용하는 동안 콜백은 Activity에서 정의되어야합니다 .
getContext().getClass().getMethod()
call은 메소드 검색을 현재 컨텍스트 (Fragment의 경우 Activity)로 제한합니다. 따라서 메소드는 Fragment 클래스가 아닌 Activity 클래스 내에서 검색됩니다. - 콜백 방법은보기 매개 변수를 받아 들여야한다 가입일 :
Java Class getMethod
받아들이는 방법에 대한 검색View.class
매개 변수로합니다.
답변
여기에 매우 좋은 답변이 있지만 한 줄을 추가하고 싶습니다.
에서 android:onclick
XML에서, 안드로이드는 사용하는 자바 반사를 이 처리하는 장면 뒤에.
그리고 여기에 설명 된 바와 같이, 반사는 항상 성능이 저하. (특히 Dalvik VM에서). 등록 onClickListener
하는 것이 더 좋은 방법입니다.
답변
onClick XML 기능을 사용하려면 해당 메소드에 하나의 매개 변수가 있어야하며이 매개 변수의 유형은 XML 오브젝트와 일치해야합니다.
예를 들어, 버튼 은 이름 문자열을 통해 메소드에 연결 android:onClick="MyFancyMethod"
되지만 메소드 선언에는 다음이 표시되어야합니다.
...MyFancyMethod(View v) {...
이 기능을 메뉴 항목 에 추가하려고 하면 XML 파일에 동일한 구문이 사용되지만 메소드는 다음과 같이 선언됩니다....MyFancyMethod(MenuItem mi) {...