一个非常简单的组建间事件通信类
要实现组建件自由通信,Android似乎没有提供很完美的方法,但是我们知道有很多第三方的EventBus库可以实现这种功能。
不过我始终没有使用过任何一个EventBus库,因为如果代码不多就能实现这个简单的功能,我是不愿意用第三方库的。
我第一次接触到EventBus这个东西,是在研究谷歌4.0原生日历代码的时候,那个时候Android上似乎还没有人提出EventBus这个概念,但是它实现的思路对我启发很大,虽然不知道它该叫什么。也是在那个时候我开始认识到接口在Java中的重要性。相关的文章见:Android 4.0日历(calendar)源码分析之CalendarController(事件分发)
我们先来看看EventBus要解决的问题
假如我在一个登录界面登录成功,想把这个消息发送给主界面的一个tab页(比如个人中心),而这个tab是一个Fragment,这个时候就会感觉有点麻烦了,最笨的方法是从上往下,传递这个Fragment的实例。如果这种事件有三个以上,并且发生在三组不同的类之间,你的代码就会很乱了。
所以我们需要一种在任何地点发送一个消息,能被任何类接收到此消息的机制。
该怎么设计呢?
我们定义一个专门发送消息的类EventBus,并在这个类中定义一个处理消息的接口。
要满足任何地点发送消息,那么这个EventBus类可能必须使用单例,任何地点实例化它的时候都是同一对象。要把消息发送给任何类,EventBus必须在自己内部定义一个处理事件的接口,并且在内部维护一个接口的列表,当事件发送的时候,遍历这些接口,通知它们事件发生了。这里的接口就是被通知的对象,如果你的某个类要接收事件通知,实现这个接口。
还是先上代码吧,代码基本上就是从Calendar中提炼出来的。
EventBus.java
package com.jcodecraeer.app4android;
/**
* Created by jianghejie on 17/5/1.
*/
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map.Entry;
import android.content.Context;
import android.text.format.Time;
public class EventBus {
private static EventBus mController;
private LinkedHashMap<Integer,EventHandler> eventHandlers =
new LinkedHashMap<Integer,EventHandler>();
public interface EventType {
final int CATEGORY = 0;
final int TOGGLE = 1;
final int DATA = 2;
final int LOGIN = 3;
final int LOGOUT = 4;
final int THEME = 5;
}
private EventBus() {
}
public interface EventHandler {
void onHandleEvent(int eventType, Object obj);
}
public static EventBus create() {
if (mController == null) {
mController = new EventBus();
}
return mController;
}
public void sendEvent(int eventType, Object obj) {
for (Iterator<Entry<Integer, EventHandler>> handlers =
eventHandlers.entrySet().iterator(); handlers.hasNext();) {
Entry<Integer, EventHandler> entry = handlers.next();
EventHandler eventHandler = entry.getValue();
if (eventHandler != null)
eventHandler.onHandleEvent(eventType, obj);
}
}
public void registerEventHandler(int key, EventHandler eventHandler) {
synchronized (this) {
eventHandlers.put(key, eventHandler);
}
}
}
其中,create()方法创建这个类的对象,它只会返回同一个对象。EventHandler就是处理事件的接口,我们定义了一个EventHandler的LinkedHashMap,registerEventHandler(int key, EventHandler eventHandler) 方法向这个LinkedHashMap中增加EventHandler。EventType定义了事件的类型,你可以根据自己的需要添加事件类型,它只是一个数字而已。sendEvent(int eventType, Object obj)方法发送事件,eventType是事件类型,obj参数是事件携带的数据,可以在接收的时候强制转换成需要的类型。EventType是很重要的,因为EventBus会向所有注册了的EventHandler发送消息,EventType用于判断到底发来的是什么消息,从而只处理自己想要的消息。
如何使用?
以上面发送登录消息为例:
假设主界面是MainActivity,个人中心是UserFragment,登录界面是LoginActivity。
UserFragment是接收消息,LoginActivity是发送消息,因此这里UserFragment是事件处理类,所以先让它实现EventHandler接口:
public class UserFragment extends Fragment implements EventBus.EventHandler{
....
@Override
public void onHandleEvent(int eventType, Object obj) {
if(eventType == EventBus.EventType.LOGIN){
updateLoginInfo();
}
}
....
}
在MainActivity中我们我们把这个UserFragment注册到EventBus中:
EventBus.create().registerEventHandler(1,mUserFragment);
注意这里的1为mUserFragment在LinkedHashMap中的key值。
然后在LoginActivity中当登录成功的时候,发送登录成功的消息:
@Override
public void onLoginSucess(String msg) {
EventBus.create().sendEvent(EventBus.EventType.LOGIN,"登录成功");
}
总结
其实EventBus就是一个观察者模式而已,跟setOnClickListener是同一个东西,只不过它的观察者有很多个。