功能优势:1.事件使用2级标签【2个key值】,相比起单个key值,2级标签能够适应多种场合与情况,。2.监听的绑定已支持自动销毁,随着物体被销毁而注销事件,并不需要人为的操作,以减少bug。3.事件支持休眠与唤醒功能,在物体隐藏时不在响应事件的接收,唤醒后自动刷新数据。【该功能很好适用于MVC框架,主要给在UI界面使用,界面某个物体隐藏时理应不在刷新数据,而它显示出来时会强制更新一次数据】
PS:该文章部分源码依据于此在lua里实现类似unity生命周期的监听事件_Le_Sam的博客-CSDN博客
正文:
源码
local class3 = function(_name, _super)
local name = _name
local super = _super
if type(_name) ~= "string" then
name = nil
super = nil
end
local class_type = {}
class_type.ctor = false
class_type.super = super
local vtbl = {super = super, className = name}
class_type.vtbl = vtbl
setmetatable(class_type, {
__index = function( t, k )
return vtbl[k]
end,
__newindex = function(t, k, v)
vtbl[k] = v
end
})
if super then
setmetatable(vtbl, {__index =
function(t,k)
local ret = super.vtbl[k]
vtbl[k] = ret
return ret
end
})
end
class_type.new = function(...)
local obj = {}
setmetatable(obj, {__index = vtbl})
do
--[[
local create
create = function(c, ...)
if c.super then
create(c.super, ...)
end
if c.ctor then
c.ctor(obj, ...)
end
end
create(class_type, ...)
]]
if (class_type.ctor) then
class_type.ctor(obj, ...);
end
end
obj.isClassObject = true
return obj
end
return class_type
end
return class3
--[[
--Description: 事件派发器,提供事件订阅和分发接口
--]]
local class3 = require("class3")
local Helpers = require("Helpers")
local EventDispatcherEx = class3("EventDispatcherEx")
local mListener = {}
local _mGUID = 1;
-- 事件订阅
function EventDispatcherEx:RegisterEventListener(dataOwner, dataName, func, priority)
assert(type(func) == "function", "func 必须是function 类型");
priority = priority or 0;
local owner = mListener[dataOwner];
if not owner then
owner = {};
mListener[dataOwner] = owner;
end
local listeners = owner[dataName];
if not listeners then
listeners = {};
owner[dataName] = listeners;
end
local handle = _mGUID;
_mGUID = handle + 1;
listeners[handle] = {func = func, priority = priority, handle = handle};
return function()
self:UnregisterEventListener(dataOwner, dataName, handle);
end
end
-- 客户端事件取消订阅
function EventDispatcherEx:UnregisterEventListener(dataOwner, dataName, handle)
local owner = mListener[dataOwner];
if not owner then
--logwarning("DataNotificationCenter:unregister : 不存在的dataOwner");
return;
end
local listeners = owner[dataName];
if not listeners then
logwarning("DataNotificationCenter:unregister : 不存在的dataName");
return;
end
listeners[handle] = nil;
if not next(listeners) then
-- listeners空了
owner[dataName] = nil;
if not next(owner) then
mListener[dataOwner] = nil;
end
end
end
function EventDispatcherEx:UnregisterAllByDataName(dataOwnerToRemove, dataNameToRemove)
for dataOwner, owner in pairs(mListener) do
if dataOwner == dataOwnerToRemove then
for dataName, listeners in pairs(owner) do
if dataName == dataNameToRemove then
owner[dataName] = nil;
if not next(owner) then
mListener[dataOwnerToRemove] = nil;
end
return;
end
end
end
end
end
-- 客户端事件派发
function EventDispatcherEx:DispatchEvent(dataOwner, dataName, ...)
local owner = mListener[dataOwner];
if not owner then
return;
end
local listeners = owner[dataName];
if not listeners then
return;
end
local funcInfoList = {};
for _, funcInfo in pairs(listeners) do
table.insert(funcInfoList, funcInfo);
end
table.sort(funcInfoList, function(a, b)
return a.priority < b.priority;
end)
for _, v in ipairs(funcInfoList) do
if v.func then
v.func(...)
end
-- if v.func(...) then
-- self:UnregisterEventListener(dataOwner, dataName, v.handle);
-- end
end
end
-- AutoBind自动绑定,依据unity生命周期进行的绑定,物体删除后自动清除事件,物体隐藏时暂停监听,直到显示时在恢复
-- 参数,使用dataOwner和dataName两层结构是为了保证独立性,单单使用key值容易混淆
--[[
tr 物体
dataOwner 1级Key ==> Tabel类型
dataName 2级Key ==> Object类型
func 回调函数
isEnableCB 物体显示时,直接触发func(),用于保持界面内的数据是最新的,默认为false
priority 优先级,默认为0
--]]
function EventDispatcherEx:AutoBind(tr, dataOwner, dataName, func, isEnableCB, priority)
assert(tr ~= nil and tostring(tr) ~= "null", "tr 必须是Transform类型");
local unregFunc = nil;
local bDestory = false;
local bUnbind = false;
local function unRegister()
if unregFunc ~= nil then
unregFunc();
end
unregFunc = nil
end
local function onEnable()
--logdebug(string.format("EventDispatcherEx AutoBind ==> onEnable name:%s", tr.name))
unRegister();
unregFunc = self:RegisterEventListener(dataOwner, dataName, func, priority);
if isEnableCB then
func();
end
end
local function onDisable()
--logdebug(string.format("EventDispatcherEx AutoBind ==> onDisable name:%s", tr.name))
unRegister();
end
local function onDestory()
--logdebug(string.format("EventDispatcherEx AutoBind ==> onDestory name:%s", tr.name))
bDestory = true;
if not bUnbind then
unRegister();
end
end
local function unBind()
bUnbind = true;
if not bDestory then
unRegister();
Helpers.RemoveEnableListener(tr, onEnable)
Helpers.RemoveDisableListener(tr, onDisable)
Helpers.RemoveDestroyListener(tr, onDestory)
end
end
Helpers.AddEnableListener(tr, onEnable)
Helpers.AddDisableListener(tr, onDisable)
Helpers.AddDestroyListener(tr, onDestory)
return unBind; -- 取消事件监听、生命周期相关监听
end
return EventDispatcherEx
示例:
-- Model-Controller
GameData = {}
GameData.UserInfo =
{
gold = 0,
}
GameData.UpdataGold = function(num)
GameData.UserInfo.gold = num
EventDispatcherEx:DispatchEvent(GameData.UserInfo, "gold", GameData.UserInfo.gold)
end
return GameData
-- View
local UITest = ClassView("UITest")
local EventDispatcherEx = require("EventDispatcherEx")
function UITest:OnCreate()
self.goldTxt = self:FindChild("goldTxt"):GetComponent("Text")
self:InitEvent()
end
function UITest:InitEvent()
local function updataGoldInfo()
local num = 0;
if GameData.UserInfo.gold ~= nil then
num = GameData.UserInfo.gold
end
self.goldTxt.text = tostring(num);
end
EventDispatcherEx:AutoBind(self.goldTxt.transform, GameData.UserInfo, "gold", updataGoldInfo)
end
-- Test
local Main = {}
local GameData= require("GameData")
function Main.Start()
GameData.UpdataGold(10086)
end
Main.Start()
return Main
结语:GameData.UpdataGold接口还可以更进一步的优化,改为数据绑定的方式【此方式自动调用DispatchEvent接口,减少手写“EventDispatcherEx:DispatchEvent()”】
后续内容。。。敬请期待