性感码农,在线解答:有什么问题可以扫屏幕右方二维码加我微信或者在下方留言。

下面简单用报社订阅报纸的方式说一下什么是消息订阅。

报社是消息中心(MessageCenter),《人民日报》是消息体(Message),报纸上的信息是消息。人通过报社订阅《人民日报》,当《人民日报》的报纸到达报社,则给每个订阅人派发报纸。报纸到达每个订阅人手里,订阅人对报纸上的信息进行阅读处理。当订阅人出现意外状况(例如人间蒸发)不再需要报纸时,一定要取消订阅。如不取消,下次的报纸依然会派发过来,但是无人处理。现实中不会出什么问题,但在程序中就会出错。

下面上代码

using System.Collections.Generic;

//消息体
public class Message
{
    public string Name  //发送消息的名称
    {
        get;
    }

    public object Body  //消息主体
    {
        get;
    }
    public Message(string name, object body)
    {
        Name = name;
        Body = body;
    }
}

//消息中心
public class MessageCenter
{
    public delegate void MessageDelHandle(Message message);
    private readonly Dictionary<string, MessageDelHandle> _messageMap = new Dictionary<string, MessageDelHandle>();
    
    private static MessageCenter _instance;
    public static MessageCenter GetInstance()
    {
        return _instance ?? (_instance = new MessageCenter());
    }

    //添加监听
    public void AddListener(string messageName, MessageDelHandle handle = null)
    {
        if (handle == null) return;
        if (!_messageMap.ContainsKey(messageName))
        {
            _messageMap.Add(messageName, handle);
        }
        else
        {
            _messageMap[messageName] -= handle;//避免重复添加
            _messageMap[messageName] += handle;
        }
    }

    //移除监听
    public void RemoveListener(string messageName, MessageDelHandle handle = null)
    {
        if (handle == null) return;
        if (_messageMap.ContainsKey(messageName))
        {
            _messageMap[messageName] -= handle;
        }

        if (_messageMap[messageName] == null)
        {
            _messageMap.Remove(messageName);
        }
    }

    //发送消息
    public void EmitMessage(string messageName, object body = null)
    {
        if (!_messageMap.ContainsKey(messageName)) return;
        _messageMap.TryGetValue(messageName, out var handle);
        if (handle != null)
        {
            handle(new Message(messageName, body));
        }
    }
}

使用方法:

using UnityEngine;

public class SceneInit : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        //订阅消息
        MessageCenter.GetInstance().AddListener("test", Test1);
        MessageCenter.GetInstance().AddListener("test", Test2);
    }

    private void OnDestroy()
    {
        //取消订阅
        MessageCenter.GetInstance().RemoveListener("test", Test1);
        MessageCenter.GetInstance().RemoveListener("test", Test2);
    }

    private static void Test1(Message message)
    {
        Debug.Log(1);
    }
    
    private static void Test2(Message message)
    {
        Debug.Log(message.Name);
        Debug.Log(message.Body);
//        var a = (int[]) message.Body;
//        var a = (Hashtable) message.Body;
    }

    public void OnBtnClk(string btnType)
    {
        switch (btnType)
        {
            case "send":
                //消息的body可以使用任何数据类型,在使用时注意对数据进行类型转换
                MessageCenter.GetInstance().EmitMessage("test", "123123123");
//                MessageCenter.GetInstance().EmitMessage("test", new Hashtable(){{"abc", 123}});
//                MessageCenter.GetInstance().EmitMessage("test", new int[]{1, 2, 3});
                break;
        }
    }
}

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注