집 >백엔드 개발 >XML/RSS 튜토리얼 >XML 레이아웃으로 보기 클릭 이벤트 설정 사례 공유
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; }isRestricted는 현재 Context 인스턴스가 제한된 상태인지 확인하는 데 사용됩니다. 공식 설명에 따르면 제한된 상태의 Context는 XML과 같은 특정 기능을 무시합니다. 우리가 보고 있는
그러나 isRestricted 메소드는 다음 중 하나입니다. Context에 있는 소수 대부분은 구체적인 구현 방법을 가지고 있습니다(나머지는 기본적으로 추상 방법입니다). 여기서는 false를 직접 반환하며 이 방법은 ContextWrapper 및 MockContext android:onClick
를 작성할 때만 사용되므로 여기서 isRestricted는 사용자 정의 ContextWrapper를 사용하고 isRestricted를 다시 작성하지 않는 한 기본적으로 false만 반환합니다.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는
단위 테스트
View로 돌아가서
는 실제로 에서 "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't search up the hierarchy, null out and fail.
context = null;
}
}
final int id = mHostView.getId();
final String idText = id == NO_ID ? "" : " with id '"
+ mHostView.getContext().getResources().getResourceEntryName(id) + "'";
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로 빠르게 콜백할 수 있음을 의미합니다. 또한
는 주로 Lazy Loading
의 역할을 합니다. 클릭 콜백에 어떤 메소드가 사용되는지 알 수 있습니다.android:onClick
마지막으로 추가해야 할 점은
을 성급하게 사용하면 활동이 "오염"될 수 있습니다. android:onClick
위 내용은 XML 레이아웃으로 보기 클릭 이벤트 설정 사례 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!