>  기사  >  백엔드 개발  >  XML 레이아웃으로 보기 클릭 이벤트 설정 사례 공유

XML 레이아웃으로 보기 클릭 이벤트 설정 사례 공유

黄舟
黄舟원래의
2017-03-17 17:25:491485검색

    view.setOnClickListener(onClickListener);
와 같은 View에 대해 클릭 모니터링

이벤트

를 설정하는 것이 일반적입니다. 또 다른 방법은 XML 레이아웃 콜백 메서드를 사용하는 경우 먼저

    public void onClickView(View view){
        // do something
    }

와 같은 액티비티에 콜백 메서드를 작성한 다음 XML로 보기

android:onClick 속성을 ​​설정해야 합니다.

    <View
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:onClick="onClickView" />

때로는 XML 레이아웃에서 직접 클릭 이벤트를 설정하는 것이 더 편리합니다(특히 DEMO 프로젝트를 작성할 때). 일반적으로 이 방법을 사용하는 사람은 많지 않습니다. 뷰가 실행 중이어야 합니다. 이 접근 방식은 인터페이스를 사용하지 않기 때문에 리플렉션을 사용하여 활동에서 "onClickView" 메서드를 찾아 호출하세요.

다음으로 View가 소스 코드에서 콜백 메서드를 트리거하는 방법을 분석할 수 있습니다.
public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        this(context);

        final TypedArray a = context.obtainStyledAttributes(
                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
                
        for (int i = 0; i < N; i++) {
            int attr = a.getIndex(i);
            switch (attr) {
                ……
                // 处理onClick属性
                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) {
                        // 给当前View实例设置一个DeclaredOnClickListener监听器
                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
                    }
                    break;
                }
        }
}
onClick 속성을 처리할 때 먼저 View의 Context가 Restricted인지 확인하고, 그렇다면 IllegalStateException을 발생시킵니다. isRestricted 메소드를 살펴보세요.

    /**
     * Indicates whether this Context is restricted.
     *
     * @return {@code true} if this Context is restricted, {@code false} otherwise.
     *
     * @see #CONTEXT_RESTRICTED
     */
    public boolean isRestricted() {
        return false;
    }
XML 레이아웃으로 보기 클릭 이벤트 설정 사례 공유isRestricted는 현재 Context 인스턴스가 제한된 상태인지 확인하는 데 사용됩니다. 공식 설명에 따르면 제한된 상태의 Context는 XML과 같은 특정 기능을 무시합니다. 우리가 보고 있는
속성과 같은 특정 속성도 무시됩니다.

제한된 컨텍스트는 특정 기능을 비활성화할 수 있습니다. 예를 들어 제한된 컨텍스트와 연결된 보기는 특정 XML 속성을 무시합니다.

그러나 isRestricted 메소드는 다음 중 하나입니다. Context에 있는 소수 대부분은 구체적인 구현 방법을 가지고 있습니다(나머지는 기본적으로 추상 방법입니다). 여기서는 false를 직접 반환하며 이 방법은 ContextWrapper 및 MockContext android:onClick

public class ContextWrapper extends Context {
    Context mBase;
    @Override
    public boolean isRestricted() {
        return mBase.isRestricted();
    }
}

public class MockContext extends Context {
    @Override
    public boolean isRestricted() {
        throw new UnsupportedOperationException();
    }
}

ContextWrapper에서만 재정의됩니다. 또한 mBase의 isRestricted를 호출하는 프록시일 뿐이며 MockContext는

단위 테스트
를 작성할 때만 사용되므로 여기서 isRestricted는 사용자 정의 ContextWrapper를 사용하고 isRestricted를 다시 작성하지 않는 한 기본적으로 false만 반환합니다.

View로 돌아가서
는 실제로 XML 레이아웃으로 보기 클릭 이벤트 설정 사례 공유에서 "onClickView"의

문자열

을 가져온 다음 현재 보기의 인스턴스와 "onClickView"를 사용하여 DeclaredOnClickListener 인스턴스를 생성합니다. 현재 뷰의 클릭 리스너로 설정합니다.

/**
     * An implementation of OnClickListener that attempts to lazily load a
     * named click handling method from a parent or ancestor context.
     */
private static class DeclaredOnClickListener implements OnClickListener {
        private final View mHostView;
        private final String mMethodName;

        private Method mMethod;

        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
            mHostView = hostView;
            mMethodName = methodName;
        }

        @Override
        public void onClick(@NonNull View v) {
            if (mMethod == null) {
                mMethod = resolveMethod(mHostView.getContext(), mMethodName);
            }

            try {
                mMethod.invoke(mHostView.getContext(), v);
            } catch (IllegalAccessException e) {
                throw new IllegalStateException(
                        "Could not execute non-public method for android:onClick", e);
            } catch (InvocationTargetException e) {
                throw new IllegalStateException(
                        "Could not execute method for android:onClick", e);
            }
        }

        @NonNull
        private Method resolveMethod(@Nullable Context context, @NonNull String name) {
            while (context != null) {
                try {
                    if (!context.isRestricted()) {
                        return context.getClass().getMethod(mMethodName, View.class);
                    }
                } catch (NoSuchMethodException e) {
                    // Failed to find method, keep searching up the hierarchy.
                }

                if (context instanceof ContextWrapper) {
                    context = ((ContextWrapper) context).getBaseContext();
                } else {
                    // Can&#39;t search up the hierarchy, null out and fail.
                    context = null;
                }
            }

            final int id = mHostView.getId();
            final String idText = id == NO_ID ? "" : " with id &#39;"
                    + mHostView.getContext().getResources().getResourceEntryName(id) + "&#39;";
            throw new IllegalStateException("Could not find method " + mMethodName
                    + "(View) in a parent or ancestor Context for android:onClick "
                    + "attribute defined on view " + mHostView.getClass() + idText);
        }
}
여기서 보기를 클릭하면 DeclaredOnClickListener 인스턴스의 "onClick" 메서드가 호출된 다음 리플렉션을 사용하여 다음에서 호출된 메서드를 찾는 "resolveMethod" 메서드가 호출된다는 것이 분명합니다. View의 Context. "onClickView" 메소드에서 이 메소드는 View 유형의 매개변수를 가지며 마지막으로 리플렉션을 사용하여 이 메소드를 호출합니다. "onClickView" 메소드는 공개 유형이어야 하며, 그렇지 않으면 리플렉션 호출이 이루어질 때 IllegalAccessException이 발생합니다.
final String handlerName = a.getString(attr);동시에 android:onClick="onClickView"을 사용하여 클릭 이벤트를 설정하는 방법은 Context에서 콜백 메소드를 찾는 것임을 소스 코드에서 알 수 있으므로 XML로 View를 생성하면 Fragment 자체가 컨텍스트가 아니기 때문에 Fragment에서 이 메서드를 바인딩할 수 없습니다. 여기서 뷰의 컨텍스트는 실제로 FragmentActivity입니다. 이는 또한 이 메서드가 Fragment에서 FragmentActivity로 빠르게 콜백할 수 있음을 의미합니다. 또한

의 기능은 DeclaredOnClickListener 클래스의 주석에서도 확인할 수 있습니다.

는 주로 Lazy Loading

의 역할을 합니다. 클릭 콜백에 어떤 메소드가 사용되는지 알 수 있습니다.

android:onClick마지막으로 추가해야 할 점은

을 사용하여 보기에 대한 클릭 이벤트를 설정하는 것은 인터페이스가 아닌 공개 메소드를 활동에 추가하는 것을 의미한다는 것입니다. 현재 Android 개발 추세는 "Activity 클래스에 비즈니스 로직을 작성하지 마세요."입니다. 이는 프로젝트 유지 관리에 유익하고 Activity 폭발을 방지하므로 Activity에 비인터페이스 및 비라이프사이클 공개 메서드를 포함하지 않도록 하세요. 따라서

을 성급하게 사용하면 활동이 "오염"될 수 있습니다. android:onClick

위 내용은 XML 레이아웃으로 보기 클릭 이벤트 설정 사례 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.