MsgCenter——进程内消息传递的框架

MsgCenter

MsgCenter是本人自己实现的进程内的消息传递的框架。该框架是我在Github上的工程SxLibrary的一部分。

https://github.com/tangrb/SxLibrary

为什么要实现MsgCenter?

前几天去面试,被人问及如何在Android的各个组件之间传递消息,我当时给了很多中答案。例如,在Activity之间可以通过Intent来传递消息,在Fragment之间可以通过回调来进行通信,或者设置一个全局变量,然后一个组件去设置,一个组件去读取。然后面试官问我有没有使用过EventBus,使用EventBus可以方便在不同组件之间传递消息。我当时愣了一下,因为我只听说过有这个框架,但是没有使用过。

面试回来后很受挫,甚至怀疑自己是不是out了。过了大概一两天后,我就有了自己实现一个类EventBus的框架的想法。于是那天我花了半天实现实现了一个初步的可用的MsgCenter。当然这个前提是我没有看EventBus的源码,只看了EventBus的基本使用方法。如果看了EventBus源码的话,那就没什么意思了。

直到今天,我重构了MsgCenter并使得MsgCenter稳定起来。

MsgCenter的架构、设计

MsgCenter使用了生产者/消费者模型,生产者负责产生并发布消息,消费者负责订阅消息,连接生产者和消费者的是MsgCenter,MsgCenter负责缓存消息,并将消息传递到匹配的消费者手里。一个消息可以被多个消费者订阅。

初始化MsgCenter
MsgCenter.instance();

该方法用来实例化一个MsgCenter对象,MsgCenter目前采用的是单例模式。
该方法只能在主线程中调用,因为MsgCenter内部要实例化一个Handler对象,该Handler对象用来将消息回调到主线程中。

发布消息
MsgCenter.instance().publish(String msgName, int msgType, Object msgEntity);

该方法可以在任何线程中使用。

msgName用来表示该消息的名称,msgName不能为null和长度为0的字符串。

msgType表示该消息的类型,MsgType接口中定于了4种消息类型,消息解析请看MsgType的源码:

package com.trb.sxlibrary.msg;

public interface MsgType {
    /**
     * 实时消息,一旦发布就会被立即消耗。
     * 如果有该消息的订阅者,则订阅者会收到该消息,该消息被消耗掉;
     * 如果没有该消息的订阅者,该消息会被抛弃、销毁。
     * <p>
     * 该类消息的消息订阅者只能在非UI线程中接收到该消息。
     */
    int RT = 1;

    /**
     * 粘性消息,发布后该消息缓存到消息列表中。
     * 如果有该消息的订阅者,则订阅者会收到该消息,该消息被消耗掉;
     * 如果没有该消息的订阅者,该消息会一直存在于消息列表中。
     * <p>
     * 该类消息的消息订阅者只能在非UI线程中接收到该消息。
     */
    int STICKY = 2;

    /**
     * 作用同RT。
     * <p>
     * 该类消息的消息订阅者只能在UI线程中接收到该消息。
     */
    int RT_UI = 11;

    /**
     * 作用同STICKY。
     * <p>
     * 该类消息的消息订阅者只能在UI线程中接收到该消息。
     */
    int STICKY_UI = 12;
}
订阅消息
MsgCenter.instance().subscribe(String msgName, MsgListener l);

该方法用来订阅消息。

扫描二维码关注公众号,回复: 1616310 查看本文章

在这里,我认为消息只需要消息名就可以和订阅者产生关联,所以订阅的时候可以不需要消息的类型。

取消订阅消息
MsgCenter.instance().subscribe(String msgName, MsgListener l);

在第一版的时候,我考虑过使用WeakReference来包装MsgListener对象,但是最终版放弃了,我觉得还是要手动去注销,因为GC不能保证及时释放MsgListener对象。

销毁
 MsgCenter.destroy();

该方法用来停止MsgCenter的工作,内部是停止了一个解析分发消息的线程,然后释放了MsgCenter对象。

使用示例
package com.trb.sxlibrary;

import android.os.Bundle;
import android.util.Log;

import com.trb.sxlibrary.app.SxActivity;
import com.trb.sxlibrary.msg.MsgCenter;
import com.trb.sxlibrary.msg.MsgListener;
import com.trb.sxlibrary.msg.MsgType;

import org.xutils.view.annotation.ContentView;

@ContentView(R.layout.activity_main)
public class MainActivity extends SxActivity implements MsgListener {
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        MsgCenter.instance();
        testMsgCenter();
    }

    @Override
    protected void onDestroy() {
        MsgCenter.instance().unsubscribe("msg_test", MainActivity.this);
        MsgCenter.instance().unsubscribe("msg_test_ui", MainActivity.this);
        MsgCenter.destroy();
        super.onDestroy();
    }

    private void testMsgCenter() {
        Log.i(TAG, "testMsgCenter: ");
        new Thread() {
            @Override
            public void run() {
                MsgCenter.instance().subscribe("msg_test", MainActivity.this);
                MsgCenter.instance().subscribe("msg_test_ui", MainActivity.this);

                try {
                    sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                new MsgSendThread().start();
            }
        }.start();
    }

    @Override
    public void onMsgArrived(String nameName, Object msg) {
        Log.i(TAG, "onRecvMsg: " + msg);
    }

    class MsgSendThread extends Thread {
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                MsgCenter.instance().publish("msg_test", MsgType.RT, "test msg: " + +i);
                try {
                    sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                MsgCenter.instance().publish("msg_test_ui", MsgType.RT_UI, "test msg ui : " + +i);
                try {
                    sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

猜你喜欢

转载自blog.csdn.net/yumeizui8923/article/details/80716262