Android 全局消息通知框架实现(类似EventBus)

3 篇文章 0 订阅
1 篇文章 0 订阅

Android 全局消息通知框架实现(类似EventBus)


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);

三、源码解析(以Activity为例)

注册事件

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值