EventNotifyCenter

来源:互联网 发布:ug编程实例教程零件 编辑:程序博客网 时间:2024/06/08 11:00

EventNotifyCenter

该框架实现了和EventBus类似的功能,简化了应用程序内各组件间、组件与后台线程间的通信。比如请求网络,等网络返回时通过Handler或Broadcast通知UI,两个Fragment之间需要通信,这些需求都可以通过EventNotifyCenter实现。

该框架使用Java运行时级别的注解配合反射来搭建,下面是主要的类:

框架的结构非常简单,一共只有五个类 :

  1. ICallback : 接口回调

  2. CallbackHandler : Handler的子类,实现了ICallback接口,当回调callback()方法的时候,实际上调用了Handler的sendMessage()方法.最终在Handler的handleMessage()方法中,通过反射回调.

  3. EventNotifyCenter ; 对外暴露的类,

  4. EventNotifier : 将add(),remove(),notifyCallbacks()的方法封装在了此类.

  5. CallbackWrapper : ICallback的包装类

接下来具体分析下代码:

EventNotifier

    @Retention(RetentionPolicy.RUNTIME)    @Target(ElementType.METHOD)    public @interface MessageHandler {        public int message();    }

基本使用 :

//在Activity 中注册事件,: protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        EventNotifyCenter.add(HttpEvent.class, mHttpCallback);    } EventNotifyCenter.add(HttpEvent.class, mHttpCallback); ...   //销毁事件:   @Override    protected void onDestroy() {        super.onDestroy();        EventNotifyCenter.remove(mHttpCallback);    }

注册事件

首先看下add()方法 :
1. 第一个参数作为key 存储到hashMap当中
2. 第二个参数为实现回调的类,也就是CallbackHandler;

    public static void add(Class<?> callerCls, Object receiver) {       ICallback callback = getCallback(receiver);        if (callback != null) {            mNotifier.add(callerCls, callback);        }    }

其中getCallback() 获取 ICallback对象

 private static ICallback getCallback(Object receiver) {        ICallback callback = null;        if (receiver instanceof ICallback) {            callback = (ICallback) receiver;        } else {            CallbackWrapper wrapper = new CallbackWrapper(receiver);            if (wrapper.isValid()) {                callback = wrapper;            }        }        return callback;    }

如果callback不为null,调用 mNotifier.add(callerCls, callback);之前说过,事件的注册,发布,销毁都封装在了EventNotifier中,具体看下销毁都封装在了EventNotifier中的add()方法:

    public void add(Object key, ICallback callback) {        CopyOnWriteArraySet<ICallback> set = getSet(key, true);        removeCallbackFromSet(set,callback);        set.add(callback);    }    ...      private void removeCallbackFromSet(CopyOnWriteArraySet<ICallback> set,                                       ICallback callback) {        if (set == null || callback == null) {            return;        }        set.remove(callback);    }    .... private CopyOnWriteArraySet<ICallback> getSet(Object key, boolean create){        CopyOnWriteArraySet<ICallback> set = mCallbacks.get(key);        if (set == null) {            synchronized (this) {                if (mCallbacks.get(key) == null && create) {                    set = new CopyOnWriteArraySet<ICallback>();                    mCallbacks.put(key, set);                }                set = mCallbacks.get(key);            }        }        return set;    }

这里很好理解,将add()方法传入的Class作为key值,回调的callBack存放到CopyOnWriteArraySet,CopyOnWriteArraySet做为Value值,存放到ConcurrentHashMap()中,

但是之后的写法中感觉有问题,事件的注册首先从set中移除了回调,set中再添加这个回调,这一步是不是多余了.

发布事件

    public static void notifyEvent(Object caller, int message, Object... params) {        if (caller != null) {            if (caller instanceof Class) {                mNotifier.notifyCallbacks(caller, message, params);            } else {                mNotifier.notifyCallbacks(caller.getClass(), message, params);            }        }    }    ...public boolean notifyCallbacks(Object key, final int message, final Object... params) {        CopyOnWriteArraySet<ICallback> set = getSet(key, false);        if (set != null) {            for (final ICallback callback : set) {                mThread.execute(new Runnable() {                    @Override                    public void run() {                        callback.callback(message, params);                    }                });            }        }        return true;    }

从HashMap中拿到CopyOnWriteArraySet,遍历set,子线程调用ICallback的callback()方法,之前说过,项目通常使用的是CallbackHandler(),而项目中创建CallbackHandler对象都是在主线程,也就是说最终事件的调用都是在主线程来执行.

==但是这里有点问题,项目当中用到最多的就是HttpEvent.class作为key,那么性能上就可能有些影响==

当我多跳转几次页面,会发现HttpEvent 注册的事件会越来越多,而每次发布事件,都要遍历set,线程池执行任务,虽然线程池有缓存好的线程,但是如果一个页面有3个事件发布,那么意味着,这个线程池同一时间最多有48个线程,虽然线程池可以复用线程,但是同时创建这么多线程,对性能上有影响!

我们可以看到同一时间执行这么多的回调:

    @Override    public void callback(int msg, Object... params) {        if (canHandleMessage(msg)) {            Message message = obtainMessage();            message.what = msg;            message.obj = params;            sendMessage(message);        }    }    public boolean canHandleMessage(int message) {        return getMessageHandler(message) != null;    }    private synchronized Method getMessageHandler(int message) {        if (mHandlerMap == null) {            initHandlers();        }        return mHandlerMap.get(message);    }

只是在callback的时候有处理,判断CallbackHandler是否有这个message.

那么messages是在什么时候存入的呢,当我们new CallbackHandler()的时候,调用了构造方法,获取所有 EventNotifyCenter.MessageHandler注解的方法,存入到 SparseArray中,在回调的时候,判断SparseArray中是否含有这个message:

    private synchronized void initHandlers() {        if (mHandlerMap == null) {            mHandlerMap = new SparseArray<Method>();        }        for (Method method : ((Object)this).getClass().getDeclaredMethods()) {            EventNotifyCenter.MessageHandler an = method.getAnnotation(EventNotifyCenter.MessageHandler.class);            if (an != null) {                mHandlerMap.put(an.message(), method);            }        }    }

销毁事件

在Activity 的onDestroy中销毁事件,参数为CallbackHandler

    @Override    protected void onDestroy() {        super.onDestroy();        EventNotifyCenter.remove(mHttpCallback);    }    public static void remove(Object receiver) {        ICallback callback = getCallback(receiver);        if (callback != null) {            mNotifier.remove(callback);        }    }    public void remove(ICallback callback) {        for (CopyOnWriteArraySet<ICallback> set : mCallbacks.values()) {            removeCallbackFromSet(set, callback);        }    }    private void removeCallbackFromSet(CopyOnWriteArraySet<ICallback> set,                                       ICallback callback) {        if (set == null || callback == null) {            return;        }        set.remove(callback);    }

可以看到销毁事件,实际上遍历 mCallbacks ,再从set中移除callback,其实这样的话,如果有多个key,那么需要移除多次:

整个 EventNotifyCenter 的分析到这里就结束了, 可以看到整个框架的实现非常简单,但是涉及到的东西也不少,但还是有很多值得学习的地方.

0 0
原创粉丝点击