动态代理—IOC框架

作者: 香沙小熊 | 来源:发表于2017-07-04 10:35 被阅读117次

    第一个部分- XUtils框架2.0实现:事件注入、资源注入、保存数据注入
    1、注入事件
    XUtils2.0框架实现

    import android.app.Activity;
    import android.preference.Preference;
    import android.preference.PreferenceActivity;
    import android.preference.PreferenceGroup;
    import android.view.View;
    import com.lidroid.xutils.util.LogUtils;
    import com.lidroid.xutils.view.EventListenerManager;
    import com.lidroid.xutils.view.ResLoader;
    import com.lidroid.xutils.view.ViewFinder;
    import com.lidroid.xutils.view.ViewInjectInfo;
    import com.lidroid.xutils.view.annotation.ContentView;
    import com.lidroid.xutils.view.annotation.PreferenceInject;
    import com.lidroid.xutils.view.annotation.ResInject;
    import com.lidroid.xutils.view.annotation.ViewInject;
    import com.lidroid.xutils.view.annotation.event.EventBase;
    
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Array;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    public class ViewUtils {
    
        private ViewUtils() {
        }
    
        public static void inject(View view) {
            injectObject(view, new ViewFinder(view));
        }
    
        public static void inject(Activity activity) {
            injectObject(activity, new ViewFinder(activity));
        }
    
        public static void inject(PreferenceActivity preferenceActivity) {
            injectObject(preferenceActivity, new ViewFinder(preferenceActivity));
        }
    
        public static void inject(Object handler, View view) {
            injectObject(handler, new ViewFinder(view));
        }
    
        public static void inject(Object handler, Activity activity) {
            injectObject(handler, new ViewFinder(activity));
        }
    
        public static void inject(Object handler, PreferenceGroup preferenceGroup) {
            injectObject(handler, new ViewFinder(preferenceGroup));
        }
    
        public static void inject(Object handler, PreferenceActivity preferenceActivity) {
            injectObject(handler, new ViewFinder(preferenceActivity));
        }
    
        @SuppressWarnings("ConstantConditions")
        private static void injectObject(Object handler, ViewFinder finder) {
    
            Class<?> handlerType = handler.getClass();
    
            // inject ContentView
            ContentView contentView = handlerType.getAnnotation(ContentView.class);
            if (contentView != null) {
                try {
                    Method setContentViewMethod = handlerType.getMethod("setContentView", int.class);
                    setContentViewMethod.invoke(handler, contentView.value());
                } catch (Throwable e) {
                    LogUtils.e(e.getMessage(), e);
                }
            }
    
            // inject view
            Field[] fields = handlerType.getDeclaredFields();
            if (fields != null && fields.length > 0) {
                for (Field field : fields) {
                    ViewInject viewInject = field.getAnnotation(ViewInject.class);
                    if (viewInject != null) {
                        try {
                            View view = finder.findViewById(viewInject.value(), viewInject.parentId());
                            if (view != null) {
                                field.setAccessible(true);
                                field.set(handler, view);
                            }
                        } catch (Throwable e) {
                            LogUtils.e(e.getMessage(), e);
                        }
                    } else {
                        ResInject resInject = field.getAnnotation(ResInject.class);
                        if (resInject != null) {
                            try {
                                Object res = ResLoader.loadRes(
                                        resInject.type(), finder.getContext(), resInject.id());
                                if (res != null) {
                                    field.setAccessible(true);
                                    field.set(handler, res);
                                }
                            } catch (Throwable e) {
                                LogUtils.e(e.getMessage(), e);
                            }
                        } else {
                            PreferenceInject preferenceInject = field.getAnnotation(PreferenceInject.class);
                            if (preferenceInject != null) {
                                try {
                                    Preference preference = finder.findPreference(preferenceInject.value());
                                    if (preference != null) {
                                        field.setAccessible(true);
                                        field.set(handler, preference);
                                    }
                                } catch (Throwable e) {
                                    LogUtils.e(e.getMessage(), e);
                                }
                            }
                        }
                    }
                }
            }
    
            // inject event
            Method[] methods = handlerType.getDeclaredMethods();
            if (methods != null && methods.length > 0) {
                for (Method method : methods) {
                    Annotation[] annotations = method.getDeclaredAnnotations();
                    //便利注解目的:为了获取我们想要的注解对象
                    if (annotations != null && annotations.length > 0) {
                        for (Annotation annotation : annotations) {
                            //获取注解类型
                            Class<?> annType = annotation.annotationType();
                            if (annType.getAnnotation(EventBase.class) != null) {
                                method.setAccessible(true);
                                try {
                                    // ProGuard:-keep class * extends java.lang.annotation.Annotation { *; }
                                    Method valueMethod = annType.getDeclaredMethod("value");
                                    Method parentIdMethod = null;
                                    try {
                                        parentIdMethod = annType.getDeclaredMethod("parentId");
                                    } catch (Throwable e) {
                                    }
                                    //获取OnClick、OnLongClick......注解身上的value方法
                                    //values说白了就是控件的id数组
                                    Object values = valueMethod.invoke(annotation);
                                    Object parentIds = parentIdMethod == null ? null : parentIdMethod.invoke(annotation);
                                    int parentIdsLen = parentIds == null ? 0 : Array.getLength(parentIds);
                                    //获取数组长度
                                    int len = Array.getLength(values);
                                    //遍历id数组
                                    for (int i = 0; i < len; i++) {
                                        ViewInjectInfo info = new ViewInjectInfo();
                                        //获取数组中试图的id(一个的id)
                                        info.value = Array.get(values, i);
                                        info.parentId = parentIdsLen > i ? (Integer) Array.get(parentIds, i) : 0;
                                        EventListenerManager.addEventMethod(finder, info, annotation, handler, method);
                                    }
                                } catch (Throwable e) {
                                    LogUtils.e(e.getMessage(), e);
                                }
                            }
                        }
                    }
                }
            }
        }
    
    }
    

    绑定事件(通过动态代理实现) EventListenerManager.Java

    import android.view.View;
    import com.lidroid.xutils.util.LogUtils;
    import com.lidroid.xutils.util.DoubleKeyValueMap;
    import com.lidroid.xutils.view.annotation.event.EventBase;
    
    import java.lang.annotation.Annotation;
    import java.lang.ref.WeakReference;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.HashMap;
    
    public class EventListenerManager {
    
        private EventListenerManager() {
        }
    
        /**
         * k1: viewInjectInfo
         * k2: interface Type
         * value: listener
         */
        private final static DoubleKeyValueMap<ViewInjectInfo, Class<?>, Object> listenerCache =
                new DoubleKeyValueMap<ViewInjectInfo, Class<?>, Object>();
    
        public static void addEventMethod(
                ViewFinder finder,
                ViewInjectInfo info,
                Annotation eventAnnotation,
                Object handler,
                Method method) {
            try {
                View view = finder.findViewByInfo(info);
                if (view != null) {
                    EventBase eventBase = eventAnnotation.annotationType().getAnnotation(EventBase.class);
                    //监听类型:OnClickListener、OnTouchListener、OnLongClickListener......
                   Class<?> listenerType = eventBase.listenerType();
                   //事件源(你要给那个View绑定监听,而且该监听对应的方法)
                   //View.setOnClickListener() View.setOnTouchListener view.setOnLongClickListener
                    String listenerSetter = eventBase.listenerSetter();
                   //监听方法:onClick方法、onTouch方法、onLongClick方法
                    String methodName = eventBase.methodName();
                    
                   //addNewMethod该属性作用:控制是否需要创建代理对象,如果缓存存在,我们不需要创建,不存在则创建
                   //false:代表创建 true:代表不创建
                    boolean addNewMethod = false;
                    //从缓存中获取提高了性能、节约了性能
                 
                    Object listener = listenerCache.get(info, listenerType);
                    DynamicHandler dynamicHandler = null;
                    if (listener != null) {
                        dynamicHandler = (DynamicHandler) Proxy.getInvocationHandler(listener);
                        addNewMethod = handler.equals(dynamicHandler.getHandler());
                        if (addNewMethod) {
                            dynamicHandler.addMethod(methodName, method);
                        }
                    }
                    if (!addNewMethod) {
                        //第一次添加监听
                        dynamicHandler = new DynamicHandler(handler);
                        dynamicHandler.addMethod(methodName, method);
    
                        //listener:代理对象
                        listener = Proxy.newProxyInstance(
                                listenerType.getClassLoader(),
                                new Class<?>[]{listenerType},
                                dynamicHandler);
    
                        //缓存
                        listenerCache.put(info, listenerType, listener);
                    }
    
                    //绑定监听
                    Method setEventListenerMethod = view.getClass().getMethod(listenerSetter, listenerType);
                    setEventListenerMethod.invoke(view, listener);
                }
            } catch (Throwable e) {
                LogUtils.e(e.getMessage(), e);
            }
        }
    
     
        //WeakReference?为什么?
        //第一点:及时清理内存
        //第二点:Activity很有可能会被意外释放(意外关闭,而这个时候你刚好执行代码到了控件的加载)
        //添加弱引用目的:为了防止对象意外被释放关闭而产生异常(典型:空指针异常)
        public static class DynamicHandler implements InvocationHandler {
            private WeakReference<Object> handlerRef;
            private final HashMap<String, Method> methodMap = new HashMap<String, Method>(1);
            
           //动态代理 持有目标对象:代表Activity或者Fragment
            public DynamicHandler(Object handler) {
                this.handlerRef = new WeakReference<Object>(handler);
            }
    
            public void addMethod(String name, Method method) {
                methodMap.put(name, method);
            }
    
            public Object getHandler() {
                return handlerRef.get();
            }
    
            public void setHandler(Object handler) {
                this.handlerRef = new WeakReference<Object>(handler);
            }
    
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object handler = handlerRef.get();
                if (handler != null) {
                    String methodName = method.getName();
                    method = methodMap.get(methodName);
                    //目的:确定代理需要的方法
                    if (method != null) {
                        return method.invoke(handler, args);
                    }
                }
                return null;
            }
        }
    }
    

    ViewInjectInfo类作用保存控件id类
    将来我要扩展该类的属性 控制功能逻辑

    public class ViewInjectInfo {
        public Object value;
        public int parentId;
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof ViewInjectInfo)) return false;
    
            ViewInjectInfo that = (ViewInjectInfo) o;
    
            if (parentId != that.parentId) return false;
            if (value == null) return (null == that.value);
    
            return value.equals(that.value);
        }
    
        @Override
        public int hashCode() {
            int result = value.hashCode();
            result = 31 * result + parentId;
            return result;
        }
    }
    

    2.优化一下
    优化第一步:设置方法访问权限:method.setAccessible(true); 允许访问 private形式
    优化第二步:缓存优化

    缺陷:注解类过于庞大。 框架变得越来越臃肿
    第二个部分:XUtils框架3.0实现核心架构原理:整体架构做了重写
    就一个模块进行分析(ViewUtils模块)
    问题:我们Android有多少个监听,你就要定义多少个注解类?(XUtils2.0实现)
    2.0注解类过于庞大。 框架变得越来越臃肿

                XUtils3.0之后整体架构大的改进和升级
    

    四大接口模块都通过简单工厂类获取,同受采用了静态内部类单例模式

    package org.xutils;
    
    import android.app.Application;
    import android.content.Context;
    
    import org.xutils.common.TaskController;
    import org.xutils.common.task.TaskControllerImpl;
    import org.xutils.db.DbManagerImpl;
    import org.xutils.http.HttpManagerImpl;
    import org.xutils.image.ImageManagerImpl;
    import org.xutils.view.ViewInjectorImpl;
    
    import java.lang.reflect.Method;
    
    import javax.net.ssl.HostnameVerifier;
    import javax.net.ssl.HttpsURLConnection;
    
    
    /**
     * Created by wyouflf on 15/6/10.
     * 任务控制中心, http, image, db, view注入等接口的入口.
     * 需要在在application的onCreate中初始化: x.Ext.init(this);
     */
    public final class x {
    
        private x() {
        }
    
        public static boolean isDebug() {
            return Ext.debug;
        }
    
        public static Application app() {
            if (Ext.app == null) {
                try {
                    // 在IDE进行布局预览时使用
                    Class<?> renderActionClass = Class.forName("com.android.layoutlib.bridge.impl.RenderAction");
                    Method method = renderActionClass.getDeclaredMethod("getCurrentContext");
                    Context context = (Context) method.invoke(null);
                    Ext.app = new MockApplication(context);
                } catch (Throwable ignored) {
                    throw new RuntimeException("please invoke x.Ext.init(app) on Application#onCreate()"
                            + " and register your Application in manifest.");
                }
            }
            return Ext.app;
        }
    
        public static TaskController task() {
            return Ext.taskController;
        }
    
        public static HttpManager http() {
            if (Ext.httpManager == null) {
                HttpManagerImpl.registerInstance();
            }
            return Ext.httpManager;
        }
    
        public static ImageManager image() {
            if (Ext.imageManager == null) {
                ImageManagerImpl.registerInstance();
            }
            return Ext.imageManager;
        }
    
        public static ViewInjector view() {
            if (Ext.viewInjector == null) {
                ViewInjectorImpl.registerInstance();
            }
            return Ext.viewInjector;
        }
    
        public static DbManager getDb(DbManager.DaoConfig daoConfig) {
            return DbManagerImpl.getInstance(daoConfig);
        }
       //静态内部类单例模式
        public static class Ext {
            private static boolean debug;
            private static Application app;
            private static TaskController taskController;
            private static HttpManager httpManager;
            private static ImageManager imageManager;
            private static ViewInjector viewInjector;
    
            private Ext() {
            }
    
            public static void init(Application app) {
                TaskControllerImpl.registerInstance();
                if (Ext.app == null) {
                    Ext.app = app;
                }
            }
    
            public static void setDebug(boolean debug) {
                Ext.debug = debug;
            }
    
            public static void setTaskController(TaskController taskController) {
                if (Ext.taskController == null) {
                    Ext.taskController = taskController;
                }
            }
    
            public static void setHttpManager(HttpManager httpManager) {
                Ext.httpManager = httpManager;
            }
    
            public static void setImageManager(ImageManager imageManager) {
                Ext.imageManager = imageManager;
            }
    
            public static void setViewInjector(ViewInjector viewInjector) {
                Ext.viewInjector = viewInjector;
            }
    
            public static void setDefaultHostnameVerifier(HostnameVerifier hostnameVerifier) {
                HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
            }
        }
    
        private static class MockApplication extends Application {
            public MockApplication(Context baseContext) {
                this.attachBaseContext(baseContext);
            }
        }
    }
    

    ViewUtils模块为例:
    第一个优化改进:整体架构(采用面向接口编程 同时采用了一些设计模式)
    第二个优化改进:ViewUtils事件注解结构类进行了改进(由用户配置)
    将所有注解事件进行了合并,有用户指定对应的监听
    默认是OnClickListener监听
    性能提高了(之前是嵌套循环)

    ViewInjectorImpl.java

    /*
     * Copyright (c) 2013. wyouflf (wyouflf@gmail.com)
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package org.xutils.view;
    
    import android.app.Activity;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    
    import org.xutils.ViewInjector;
    import org.xutils.common.util.LogUtil;
    import org.xutils.view.annotation.ContentView;
    import org.xutils.view.annotation.Event;
    import org.xutils.view.annotation.ViewInject;
    import org.xutils.x;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    import java.util.HashSet;
    
    public final class ViewInjectorImpl implements ViewInjector {
    
        private static final HashSet<Class<?>> IGNORED = new HashSet<Class<?>>();
    
        static {
            IGNORED.add(Object.class);
            IGNORED.add(Activity.class);
            IGNORED.add(android.app.Fragment.class);
            try {
                IGNORED.add(Class.forName("android.support.v4.app.Fragment"));
                IGNORED.add(Class.forName("android.support.v4.app.FragmentActivity"));
            } catch (Throwable ignored) {
            }
        }
    
        private static final Object lock = new Object();
        private static volatile ViewInjectorImpl instance;
    
        private ViewInjectorImpl() {
        }
    
        public static void registerInstance() {
            if (instance == null) {
                synchronized (lock) {
                    if (instance == null) {
                        instance = new ViewInjectorImpl();
                    }
                }
            }
            x.Ext.setViewInjector(instance);
        }
    
        @Override
        public void inject(View view) {
            injectObject(view, view.getClass(), new ViewFinder(view));
        }
    
        @Override
        public void inject(Activity activity) {
            //获取Activity的ContentView的注解
            Class<?> handlerType = activity.getClass();
            try {
                ContentView contentView = findContentView(handlerType);
                if (contentView != null) {
                    int viewId = contentView.value();
                    if (viewId > 0) {
                        Method setContentViewMethod = handlerType.getMethod("setContentView", int.class);
                        setContentViewMethod.invoke(activity, viewId);
                    }
                }
            } catch (Throwable ex) {
                LogUtil.e(ex.getMessage(), ex);
            }
    
            injectObject(activity, handlerType, new ViewFinder(activity));
        }
    
        @Override
        public void inject(Object handler, View view) {
            injectObject(handler, handler.getClass(), new ViewFinder(view));
        }
    
        @Override
        public View inject(Object fragment, LayoutInflater inflater, ViewGroup container) {
            // inject ContentView
            View view = null;
            Class<?> handlerType = fragment.getClass();
            try {
                ContentView contentView = findContentView(handlerType);
                if (contentView != null) {
                    int viewId = contentView.value();
                    if (viewId > 0) {
                        view = inflater.inflate(viewId, container, false);
                    }
                }
            } catch (Throwable ex) {
                LogUtil.e(ex.getMessage(), ex);
            }
    
            // inject res & event
            injectObject(fragment, handlerType, new ViewFinder(view));
    
            return view;
        }
    
        /**
         * 从父类获取注解View
         */
        private static ContentView findContentView(Class<?> thisCls) {
            if (thisCls == null || IGNORED.contains(thisCls)) {
                return null;
            }
            ContentView contentView = thisCls.getAnnotation(ContentView.class);
            if (contentView == null) {
                return findContentView(thisCls.getSuperclass());
            }
            return contentView;
        }
    
        @SuppressWarnings("ConstantConditions")
        private static void injectObject(Object handler, Class<?> handlerType, ViewFinder finder) {
    
            if (handlerType == null || IGNORED.contains(handlerType)) {
                return;
            }
    
            // 从父类到子类递归
            injectObject(handler, handlerType.getSuperclass(), finder);
    
            // inject view
            Field[] fields = handlerType.getDeclaredFields();
            if (fields != null && fields.length > 0) {
                for (Field field : fields) {
    
                    Class<?> fieldType = field.getType();
                    if (
                    /* 不注入静态字段 */     Modifier.isStatic(field.getModifiers()) ||
                    /* 不注入final字段 */    Modifier.isFinal(field.getModifiers()) ||
                    /* 不注入基本类型字段 */  fieldType.isPrimitive() ||
                    /* 不注入数组类型字段 */  fieldType.isArray()) {
                        continue;
                    }
    
                    ViewInject viewInject = field.getAnnotation(ViewInject.class);
                    if (viewInject != null) {
                        try {
                            View view = finder.findViewById(viewInject.value(), viewInject.parentId());
                            if (view != null) {
                                field.setAccessible(true);
                                field.set(handler, view);
                            } else {
                                throw new RuntimeException("Invalid @ViewInject for "
                                        + handlerType.getSimpleName() + "." + field.getName());
                            }
                        } catch (Throwable ex) {
                            LogUtil.e(ex.getMessage(), ex);
                        }
                    }
                }
            } // end inject view
    
            // inject event
            Method[] methods = handlerType.getDeclaredMethods();
            if (methods != null && methods.length > 0) {
                for (Method method : methods) {
    
                    //注意:静态方法不允许添加控件注解,私有方法允许访问,非私有方法不允许访问
                    if (Modifier.isStatic(method.getModifiers())
                            || !Modifier.isPrivate(method.getModifiers())) {
                        continue;
                    }
    
                    //检查当前方法是否是event注解的方法
                    Event event = method.getAnnotation(Event.class);
                    if (event != null) {
                        try {
                            // id参数
                            int[] values = event.value();
                            int[] parentIds = event.parentId();
                            int parentIdsLen = parentIds == null ? 0 : parentIds.length;
                            //循环所有id,生成ViewInfo并添加代理反射
                            for (int i = 0; i < values.length; i++) {
                                int value = values[i];
                                if (value > 0) {
                                    ViewInfo info = new ViewInfo();
                                    info.value = value;
                                    info.parentId = parentIdsLen > i ? parentIds[i] : 0;
                                    method.setAccessible(true);
                                    EventListenerManager.addEventMethod(finder, info, event, handler, method);
                                }
                            }
                        } catch (Throwable ex) {
                            LogUtil.e(ex.getMessage(), ex);
                        }
                    }
                }
            } // end inject event
    
        }
    
    }
    

    在xUtils框架3.0之后,要求我们的方法必须是私有方法(注意:public不行)
    让注解方法只属于当前类

      //注意:静态方法不允许添加控件注解,私有方法允许访问,非私有方法不允许访问
                    if (Modifier.isStatic(method.getModifiers())
                            || !Modifier.isPrivate(method.getModifiers())) {
                        continue;
                    }
    
    
    /*
     * Copyright (c) 2013. wyouflf (wyouflf@gmail.com)
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package org.xutils.view;
    
    import android.text.TextUtils;
    import android.view.View;
    
    import org.xutils.common.util.DoubleKeyValueMap;
    import org.xutils.common.util.LogUtil;
    import org.xutils.view.annotation.Event;
    
    import java.lang.ref.WeakReference;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Map;
    
    /*package*/ final class EventListenerManager {
    
        private final static long QUICK_EVENT_TIME_SPAN = 300;
        private final static HashSet<String> AVOID_QUICK_EVENT_SET = new HashSet<String>(2);
    
        static {
            AVOID_QUICK_EVENT_SET.add("onClick");
            AVOID_QUICK_EVENT_SET.add("onItemClick");
        }
    
        private EventListenerManager() {
        }
    
        /**
         * k1: viewInjectInfo
         * k2: interface Type
         * value: listener
         */
        private final static DoubleKeyValueMap<ViewInfo, Class<?>, Object>
                listenerCache = new DoubleKeyValueMap<ViewInfo, Class<?>, Object>();
    
    
        public static void addEventMethod(
                //根据页面或view holder生成的ViewFinder
                ViewFinder finder,
                //根据当前注解ID生成的ViewInfo
                ViewInfo info,
                //注解对象
                Event event,
                //页面或view holder对象
                Object handler,
                //当前注解方法
                Method method) {
            try {
                View view = finder.findViewByInfo(info);
    
                if (view != null) {
                    // 注解中定义的接口,比如Event注解默认的接口为View.OnClickListener
                    Class<?> listenerType = event.type();
                    // 默认为空,注解接口对应的Set方法,比如setOnClickListener方法
                    String listenerSetter = event.setter();
                    if (TextUtils.isEmpty(listenerSetter)) {
                        listenerSetter = "set" + listenerType.getSimpleName();
                    }
    
    
                    String methodName = event.method();
    
                    boolean addNewMethod = false;
                    /*
                        根据View的ID和当前的接口类型获取已经缓存的接口实例对象,
                        比如根据View.id和View.OnClickListener.class两个键获取这个View的OnClickListener对象
                     */
                    Object listener = listenerCache.get(info, listenerType);
                    DynamicHandler dynamicHandler = null;
                    /*
                        如果接口实例对象不为空
                        获取接口对象对应的动态代理对象
                        如果动态代理对象的handler和当前handler相同
                        则为动态代理对象添加代理方法
                     */
                    if (listener != null) {
                        dynamicHandler = (DynamicHandler) Proxy.getInvocationHandler(listener);
                        addNewMethod = handler.equals(dynamicHandler.getHandler());
                        if (addNewMethod) {
                            dynamicHandler.addMethod(methodName, method);
                        }
                    }
    
                    // 如果还没有注册此代理
                    if (!addNewMethod) {
    
                        dynamicHandler = new DynamicHandler(handler);
    
                        dynamicHandler.addMethod(methodName, method);
    
                        // 生成的代理对象实例,比如View.OnClickListener的实例对象
                        listener = Proxy.newProxyInstance(
                                listenerType.getClassLoader(),
                                new Class<?>[]{listenerType},
                                dynamicHandler);
    
                        listenerCache.put(info, listenerType, listener);
                    }
    
                    Method setEventListenerMethod = view.getClass().getMethod(listenerSetter, listenerType);
                    setEventListenerMethod.invoke(view, listener);
                }
            } catch (Throwable ex) {
                LogUtil.e(ex.getMessage(), ex);
            }
        }
    
        public static class DynamicHandler implements InvocationHandler {
            // 存放代理对象,比如Fragment或view holder
            private WeakReference<Object> handlerRef;
            // 存放代理方法
            private final HashMap<String, Method> methodMap = new HashMap<String, Method>(1);
    
            private static long lastClickTime = 0;
    
            public DynamicHandler(Object handler) {
                this.handlerRef = new WeakReference<Object>(handler);
            }
    
            public void addMethod(String name, Method method) {
                methodMap.put(name, method);
            }
    
            public Object getHandler() {
                return handlerRef.get();
            }
    
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object handler = handlerRef.get();
                if (handler != null) {
    
                    String eventMethod = method.getName();
                    if ("toString".equals(eventMethod)) {
                        return DynamicHandler.class.getSimpleName();
                    }
    
                    method = methodMap.get(eventMethod);
                    if (method == null && methodMap.size() == 1) {
                        for (Map.Entry<String, Method> entry : methodMap.entrySet()) {
                            if (TextUtils.isEmpty(entry.getKey())) {
                                method = entry.getValue();
                            }
                            break;
                        }
                    }
    
                    if (method != null) {
    
                        if (AVOID_QUICK_EVENT_SET.contains(eventMethod)) {
                            long timeSpan = System.currentTimeMillis() - lastClickTime;
                            if (timeSpan < QUICK_EVENT_TIME_SPAN) {
                                LogUtil.d("onClick cancelled: " + timeSpan);
                                return null;
                            }
                            lastClickTime = System.currentTimeMillis();
                        }
    
                        try {
                            return method.invoke(handler, args);
                        } catch (Throwable ex) {
                            throw new RuntimeException("invoke method error:" +
                                    handler.getClass().getName() + "#" + method.getName(), ex);
                        }
                    } else {
                        LogUtil.w("method not impl: " + eventMethod + "(" + handler.getClass().getSimpleName() + ")");
                    }
                }
                return null;
            }
        }
    }
    

    简化Activity中得监听事件语句
    // 注解中定义的接口,比如Event注解默认的接口为View.OnClickListener
    Class<?> listenerType = event.type();
    // 默认为空,注解接口对应的Set方法,比如setOnClickListener方法
    String listenerSetter = event.setter();
    if (TextUtils.isEmpty(listenerSetter)) {
    listenerSetter = "set" + listenerType.getSimpleName();
    }
    否则 我们要在Activity中这么写

      @Event(listenerType = View.OnTouchListener.class, callbackMethod = "onTouch",listenerSetter = "setOnTouchListener",value={R.id.tv_title})
        private boolean touch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    Toast.makeText(this, "触摸按下!", Toast.LENGTH_LONG).show();
                    break;
    
                default:
                    break;
            }
            return true;
        }
    

    相关文章

      网友评论

        本文标题:动态代理—IOC框架

        本文链接:https://www.haomeiwen.com/subject/kapucxtx.html