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