publicView(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()) { thrownew 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; } } }
/** * An implementation of OnClickListener that attempts to lazily load a * named click handling method from a parent or ancestor context. */privatestaticclassDeclaredOnClickListenerimplementsOnClickListener{ privatefinal View mHostView; privatefinal String mMethodName;
try { mMethod.invoke(mHostView.getContext(), v); } catch (IllegalAccessException e) { thrownew IllegalStateException( "Could not execute non-public method for android:onClick", e); } catch (InvocationTargetException e) { thrownew 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; } }
finalint id = mHostView.getId(); final String idText = id == NO_ID ? "" : " with id '" + mHostView.getContext().getResources().getResourceEntryName(id) + "'"; thrownew IllegalStateException("Could not find method " + mMethodName + "(View) in a parent or ancestor Context for android:onClick " + "attribute defined on view " + mHostView.getClass() + idText); } }