EventNotifyCenter

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 set = getSet(key, true);
        removeCallbackFromSet(set,callback);
        set.add(callback);
    }

    ...
      private void removeCallbackFromSet(CopyOnWriteArraySet set,
                                       ICallback callback) {
        if (set == null || callback == null) {
            return;
        }
        set.remove(callback);
    }

    ....

 private CopyOnWriteArraySet getSet(Object key, boolean create){
        CopyOnWriteArraySet set = mCallbacks.get(key);
        if (set == null) {
            synchronized (this) {
                if (mCallbacks.get(key) == null && create) {
                    set = new CopyOnWriteArraySet();
                    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 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();
        }
        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 set : mCallbacks.values()) {
            removeCallbackFromSet(set, callback);
        }
    }

    private void removeCallbackFromSet(CopyOnWriteArraySet set,
                                       ICallback callback) {
        if (set == null || callback == null) {
            return;
        }
        set.remove(callback);
    }

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

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

你可能感兴趣的:(源码分析)