通过注解,对View点击事件自动上报的实现原理

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u010577768/article/details/90903983
class AnnotationResolver {
    void resolveElementsAndInputs(DAPageNumberable object) {
        Class<?> clazz = object.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            if (field == null) continue;
            for (Annotation annotation : field.getAnnotations()) {
                if (annotation instanceof DAElement) {
                    if (field.getType() == EditText.class
                            || field.getType() == AppCompatEditText.class) {
                        throw new DAAnnotationException(DAElement.class.getSimpleName() +
                                " should be used to appClick event");
                    }
                    field.setAccessible(true);
                    try {
                        View widget = (View) field.get(object);
                        View.OnClickListener listener = getOnClickListener(widget);
                        if (listener != null) {
                            widget.setOnClickListener(new DAOnClickListener(object, listener, ((DAElement) annotation).id()));
                        } else {
                            widget.setOnClickListener(new DAOnClickListener(object, ((DAElement) annotation).id()));
                        }
                    } catch (Exception ignored) { }
                }

                if (annotation instanceof DAInput) {
                    if (field.getType() != EditText.class
                            && field.getType() != AppCompatEditText.class) {
                        throw new DAAnnotationException(DAInput.class.getSimpleName() +
                                " should be used to appInput event");
                    }
                    field.setAccessible(true);
                    try {
                        EditText editText = (EditText) field.get(object);
                        int inputId = ((DAInput) annotation).id();
                        DAAPI.getInstance(object).appInput(inputId, editText);
                    } catch (Exception ignored) {}
                }
            }
        }
    }

    public class DAOnClickListener implements View.OnClickListener {
        DAPageNumberable mObject;
        View.OnClickListener mListener;
        int mElementId;

        DAOnClickListener(DAPageNumberable object, int elementId) {
            mObject = object;
            mElementId = elementId;
        }

        DAOnClickListener(DAPageNumberable object, View.OnClickListener listener, int elementId) {
            mObject = object;
            mListener = listener;
            mElementId = elementId;
        }

        @Override
        public void onClick(View v) {
            if (mListener != null) {
                mListener.onClick(v);
            }
            DAAPI.getInstance(mObject).appClick(mElementId);
        }
    }

    /**
     * Returns the current View.OnClickListener for the given View
     *
     * @param view the View whose click listener to retrieve
     * @return the View.OnClickListener attached to the view; null if it could not be retrieved
     */
    private static View.OnClickListener getOnClickListener(View view) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            return getOnClickListenerV14(view);
        } else {
            return getOnClickListenerV(view);
        }
    }

    //Used for APIs lower than ICS (API 14)
    private static View.OnClickListener getOnClickListenerV(View view) {
        View.OnClickListener retrievedListener = null;
        String viewStr = "android.view.View";
        Field field;

        try {
            field = Class.forName(viewStr).getDeclaredField("mOnClickListener");
            retrievedListener = (View.OnClickListener) field.get(view);
        } catch (Exception ex) {
        }

        return retrievedListener;
    }

    //Used for new ListenerInfo class structure used beginning with API 14 (ICS)
    private static View.OnClickListener getOnClickListenerV14(View view) {
        View.OnClickListener retrievedListener = null;
        String viewStr = "android.view.View";
        String lInfoStr = "android.view.View$ListenerInfo";

        try {
            Field listenerField = Class.forName(viewStr).getDeclaredField("mListenerInfo");
            Object listenerInfo = null;

            if (listenerField != null) {
                listenerField.setAccessible(true);
                listenerInfo = listenerField.get(view);
            }

            Field clickListenerField = Class.forName(lInfoStr).getDeclaredField("mOnClickListener");

            if (clickListenerField != null && listenerInfo != null) {
                retrievedListener = (View.OnClickListener) clickListenerField.get(listenerInfo);
            }
        } catch (Exception ex) {
        }

        return retrievedListener;
    }
}
展开阅读全文

没有更多推荐了,返回首页