[android] android : onClick XML 속성이 setOnClickListener와 정확히 어떻게 다릅니 까?

나는 당신이 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:onclickXML에서, 안드로이드는 사용하는 자바 반사를 이 처리하는 장면 뒤에.

그리고 여기에 설명 된 바와 같이, 반사는 항상 성능이 저하. (특히 Dalvik VM에서). 등록 onClickListener하는 것이 더 좋은 방법입니다.


답변

onClick XML 기능을 사용하려면 해당 메소드에 하나의 매개 변수가 있어야하며이 매개 변수의 유형은 XML 오브젝트와 일치해야합니다.

예를 들어, 버튼 은 이름 문자열을 통해 메소드에 연결 android:onClick="MyFancyMethod"되지만 메소드 선언에는 다음이 표시되어야합니다.
...MyFancyMethod(View v) {...

이 기능을 메뉴 항목 에 추가하려고 하면 XML 파일에 동일한 구문이 사용되지만 메소드는 다음과 같이 선언됩니다....MyFancyMethod(MenuItem mi) {...