EventNotifyCenter
来源:互联网 发布:ug编程实例教程零件 编辑:程序博客网 时间:2024/06/08 11:00
EventNotifyCenter
该框架实现了和EventBus类似的功能,简化了应用程序内各组件间、组件与后台线程间的通信。比如请求网络,等网络返回时通过Handler或Broadcast通知UI,两个Fragment之间需要通信,这些需求都可以通过EventNotifyCenter实现。
该框架使用Java运行时级别的注解配合反射来搭建,下面是主要的类:
框架的结构非常简单,一共只有五个类 :
ICallback : 接口回调
CallbackHandler : Handler的子类,实现了ICallback接口,当回调callback()方法的时候,实际上调用了Handler的sendMessage()方法.最终在Handler的handleMessage()方法中,通过反射回调.
EventNotifyCenter ; 对外暴露的类,
EventNotifier : 将add(),remove(),notifyCallbacks()的方法封装在了此类.
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 的分析到这里就结束了, 可以看到整个框架的实现非常简单,但是涉及到的东西也不少,但还是有很多值得学习的地方.
- EventNotifyCenter
- python2&python3中的urllib库区别
- tcpdump抓包+wireshark分析配合使用
- Spring总结笔记之四
- 【Leetcode】300. Longest Increasing Subsequence
- JNOJ Fractal
- EventNotifyCenter
- 对多线程的问题进行总结,罗列了40个多线程的问题
- jdbc连接Oracle数据库(easy to integration)
- 有趣的字符串常量
- 如何更换Ubuntu的源
- JDBC连接oracle RAC数据库配置
- linux shell demos(1)
- 静态成员函数访问构造函数
- 【树莓派】RTC时钟模块安装教程第一部分:接线