Github项目地址 https://github.com/532268948/MessageDemo
随着页面的增多,页面之间的信息交流也会越来越多,比如一个社交类app,你在个人中心修改了自己的个人信息,在动态展示页面你就要通知该页面有关于自己的动态需要更新自己展示在页面上的信息。
该框架的核心思想是在进入页面的的时候注册监听器,每一类事件监听器都有一个唯一标志符用来区分不同的事件,时间传递信息的媒介是Message,就是Handler中的,在Message中你可以传输自己想传的数据。
//注册事件
MessageManager.getInstance().registerMessageReceiver(this, "user_info_change", new MessageLooper.OnMessageListener() {
@Override
public void onMessage(Message msg) {
if (msg != null) {
String nickname = msg.getData().getString("nickname", "");
mNicknameTv.setText(nickname);
}
}
});
//注销当前Activity或Fragment注册的事件
MessageManager.getInstance().unRegisterMessageReceiver(this);
//发送事件
MessageManager.getInstance().sendMessage("user_info_change",message);
MessageManager.java
/**
* 注册事件
*
* @param activity
* @param cmd 事件唯一标志
* @param listener 事件回调
*/
public void registerMessageReceiver(Activity activity, String cmd, MessageLooper.OnMessageListener listener) {
if (messageLooper != null) {
messageLooper.registerReceiver(cmd, listener);
}
ListenerContainer container = getListenerContainer(activity);
if (container == null) {
container = new ListenerContainer(activity);
containerList.add(container);
}
container.addListener(listener);
}
MessageLooper.java
/**
* 由于会有频繁的增、删操作,因此采用线程安全的ConCurrentHasMap(),Vector也是线程
* 安全的
*/
private Map<String, Vector<OnMessageListener>> mMessageReceiver = new ConcurrentHashMap<>();
/**
* 注册事件
*
* @param cmd 事件唯一标志
* @param listener 回调
*/
public void registerReceiver(String cmd, OnMessageListener listener) {
if (!TextUtils.isEmpty(cmd) && listener != null) {
Vector<OnMessageListener> listeners = mMessageReceiver.get(cmd);
if (listeners == null) {
listeners = new Vector<>();
}
listeners.add(listener);
this.mMessageReceiver.put(cmd, listeners);
}
}
从中可以看到有一个MessageLooper的新类,它是事件注册的核心,该类的功能是对所有注册事件进行统一管理,其中变量mMessageReceiver存储了所有的注册事件。
/**
* 将同一个Activity或Fragment的OnMessageListener放到一起,便于统一取消事件
*/
private static class ListenerContainer {
Activity activity;
Fragment fragment;
ArrayList<MessageLooper.OnMessageListener> listeners;
ListenerContainer(Activity activity) {
this.activity = activity;
}
ListenerContainer(Fragment fragment) {
this.fragment = fragment;
}
/**
* 添加监听器
*
* @param listener
*/
public void addListener(MessageLooper.OnMessageListener listener) {
if (listener != null) {
if (listeners == null) {
listeners = new ArrayList<>();
}
listeners.add(listener);
}
}
/**
* 清空监听器
*/
public void clear() {
activity = null;
fragment = null;
if (listeners != null) {
for (MessageLooper.OnMessageListener listener : listeners) {
if (listener != null) {
messageLooper.unRegisterReciver(listener);
}
}
listeners.clear();
listeners = null;
}
}
}
ListenerContainer这个类,它主要是负责将不同页面的注册事件区分,方便注销当前页面的事件,在添加事件的时候会同时添加到该页面的ListenerContainer对象中,一个ListenerContainer对象包含了一个页面的所有注册事件。
MessageManager.java
/**
* 取消事件
*
* @param activity
*/
public void unRegisterMessageReceiver(Activity activity) {
ListenerContainer container = getListenerContainer(activity);
if (container != null) {
container.clear();
}
}
ListenerContainer.java
/**
* 清空监听器
*/
public void clear() {
activity = null;
fragment = null;
if (listeners != null) {
for (MessageLooper.OnMessageListener listener : listeners) {
if (listener != null) {
messageLooper.unRegisterReciver(listener);
}
}
listeners.clear();
listeners = null;
}
}
MessageLooper.java
/**
* 注销注册事件
*
* @param listener
*/
public void unRegisterReciver(OnMessageListener listener) {
if (listener != null) {
Iterator iterator = this.mMessageReceiver.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Vector<OnMessageListener>> entry = (Map.Entry)iterator.next();
if (entry != null) {
String key = entry.getKey();
Vector<OnMessageListener> listeners = this.mMessageReceiver.get(key);
if (listeners != null && listeners.remove(listener)) {
return;
}
}
}
}
}
在调用ListenerContainer的clear()方法的时候在清空当前ContainerListener的listeners的同时清空MessageLooper中的注册事件。
MessageManager.java
/**
* 发送事件
*
* @param cmd
* @param message
*/
public void sendMessage(String cmd,Message message){
messageLooper.sendMessage(cmd,message);
}
MessageLooper.java
/**
* 发送事件
*
* @param cmd 事件唯一标志
* @param message 信息
*/
public void sendMessage(String cmd, Message message) {
if (!TextUtils.isEmpty(cmd)) {
Vector<OnMessageListener> listeners = this.mMessageReceiver.get(cmd);
if (listeners != null) {
for (int i = 0; i < listeners.size(); i++) {
OnMessageListener listener = listeners.get(i);
listener.onMessage(message);
}
}
}
}
发送事件时会遍历MessageLooper中的mMessageReceiver,如果有相同cmd的MessageListener会调用该Listener中的onMessage方法实现消息的全局接收。
Github项目地址 https://github.com/532268948/MessageDemo