事件触发器作为unity常用的模块解耦工具,其主要功能有三点:
- 订阅事件
- 移除事件
- 事件触发,并传给监听的回调方法
之前在网上看了很多帖子,通常是用一个消息体对象作为回调参数,但是我个人还是比较喜欢使用泛型的方式进行回调,参考了之前项目的工具类,便动手开始实现。话不多说,先上代码:
using System.Collections;
using System.Collections.Generic;
public class ObserverEvents
{
Dictionary<string, ArrayList> actions = null;
/// <summary>
/// 订阅
/// </summary>
public void Subscribe(string eventName, object action)
{
if (actions == null)
actions = new Dictionary<string, ArrayList>();
ArrayList callback;
if (actions.TryGetValue(eventName, out callback))
{
if (!callback.Contains(action))
callback.Add(action);
}
else
{
callback = new ArrayList();
callback.Add(action);
actions[eventName] = callback;
}
}
/// <summary>
/// 注销整个事件
/// </summary>
public void Unsubscribe(string eventName)
{
if (actions == null) return;
ArrayList callback;
if (actions.TryGetValue(eventName, out callback))
{
callback.Clear();
actions.Remove(eventName);
}
}
/// <summary>
/// 注销某一事件中的单个回调
/// </summary>
/// <param name="eventName"></param>
/// <param name="action"></param>
public void Unsubscribe(string eventName, object action)
{
if (actions == null) return;
ArrayList callback;
if (actions.TryGetValue(eventName, out callback))
{
if (callback.Contains(action))
{
callback.Remove(action);
if (callback.Count == 0)
actions.Remove(eventName);
}
}
}
public ArrayList GetActions(string eventName)
{
if (actions == null) return null;
ArrayList callBack;
if (actions.TryGetValue(eventName, out callBack))
return callBack;
return null;
}
}
ObserverEvents事件容器类,用于存储参数个数一样的不同事件
using System;
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// 事件触发器
/// </summary>
public class EventDispather
: Singleton //注释:这里其实是Singleton<EventDispather> 但是简书上Singleton后面加上'<>'就没有高亮了,不懂,有哪位兄弟能告诉一下吗?
{
private EventDispather() { }
/// <summary>
/// 创建参数个数不同的事件容器
/// </summary>
private ObserverEvents events = new ObserverEvents();
private ObserverEvents eventsT1 = new ObserverEvents();
private ObserverEvents eventsT2 = new ObserverEvents();
private ObserverEvents eventsT3 = new ObserverEvents();
#region 事件的订阅
public void SubscribeEvent(string eventName, Action<string> act)
{
events.Subscribe(eventName, act);
}
public void SubscribeEvent<T>(string eventName, Action<string, T> act)
{
eventsT1.Subscribe(eventName, act);
}
public void SubscribeEvent<T1, T2>(string eventName, Action<string, T1, T2> act)
{
eventsT2.Subscribe(eventName, act);
}
public void SubscribeEvent<T1, T2, T3>(string eventName, Action<string, T1, T2, T3> act)
{
eventsT3.Subscribe(eventName, act);
}
#endregion
#region 注销事件
public void Unsubscribe(string eventName, Action<string> act)
{
events.Unsubscribe(eventName, act);
}
public void Unsubscribe<T>(string eventName, Action<string, T> act)
{
eventsT1.Unsubscribe(eventName, act);
}
public void Unsubscribe<T1, T2>(string eventName, Action<string, T1, T2> act)
{
eventsT2.Unsubscribe(eventName, act);
}
public void Unsubscribe<T1, T2, T3>(string eventName, Action<string, T1, T2, T3> act)
{
eventsT3.Unsubscribe(eventName, act);
}
public void RemoveEvent(string eventName)
{
events.Unsubscribe(eventName);
eventsT1.Unsubscribe(eventName);
eventsT2.Unsubscribe(eventName);
eventsT3.Unsubscribe(eventName);
}
#endregion
#region 事件触发
public void PostEvent(string eventNme)
{
var actions = events.GetActions(eventNme);
if (actions != null)
{
for (int i = actions.Count - 1; i >= 0; i--)
{
var action = actions[i];
if (action == null)
actions.Remove(action);
else
{
var act = action as Action<string>;
if (act != null)
act(eventNme);
}
}
}
}
public void PostEvent<T>(string eventNme, T param)
{
var actions = eventsT1.GetActions(eventNme);
if (actions != null)
{
for (int i = actions.Count - 1; i >= 0; i--)
{
var action = actions[i];
if (action == null)
actions.Remove(action);
else
{
var act = action as Action<string, T>;
if (act != null)
act(eventNme, param);
}
}
}
}
public void PostEvent<T1, T2>(string eventNme, T1 param1, T2 param2)
{
var actions = events.GetActions(eventNme);
if (actions != null)
{
for (int i = actions.Count - 1; i >= 0; i--)
{
var action = actions[i];
if (action == null)
actions.Remove(action);
else
{
var act = action as Action<string, T1, T2>;
if (act != null)
act(eventNme, param1, param2);
}
}
}
}
public void PostEvent<T1, T2, T3>(string eventNme, T1 param1, T2 param2, T3 param3)
{
var actions = events.GetActions(eventNme);
if (actions != null)
{
for (int i = actions.Count - 1; i >= 0; i--)
{
var action = actions[i];
if (action == null)
actions.Remove(action);
else
{
var act = action as Action<string, T1, T2, T3>;
if (act != null)
act(eventNme, param1, param2, param3);
}
}
}
}
#endregion
}
EventDispather使用单例模板,具体实现请看之前的分享。
EventDispather内部创建了4个ObserverEvents事件容器,分别对应无参和至多3个参数的事件(PS:如果想更多参数的可以自行扩展),然后根据对应的事件进行注册、查找与回调
测试代码
string event_name = "test";
Action<string> act0 = (name) =>
{
Debug.Log(name);
};
Action<string, string> act1 = (name, content) =>
{
Debug.Log(name + " string: " + content);
};
Action<string, int> act2 = (name, num) =>
{
Debug.Log(name + " num: " + num);
};
//注册事件
EventDispather.Instance.SubscribeEvent(event_name, act0);
EventDispather.Instance.SubscribeEvent<string>(event_name, act1);
EventDispather.Instance.SubscribeEvent<int>(event_name, act2);
//事件提交
EventDispather.Instance.PostEvent(event_name);
EventDispather.Instance.PostEvent<string>(event_name, "你好");
EventDispather.Instance.PostEvent<int>(event_name, 521);
//注销事件
EventDispather.Instance.Unsubscribe(event_name, act0);
EventDispather.Instance.Unsubscribe<string>(event_name, act1);
EventDispather.Instance.Unsubscribe<int>(event_name, act2);
测试结果
test
test string: 你好
test num: 521
是不是感觉很easy~
但是对于我们程序员来说不只是要掌握更多的记住,更要能够温故知新,只有每天不断的学习才不会原地踏步,被世界远远的甩在身后。
最后送上我喜欢的一句话:
放弃并不难,但坚持一定很酷 !