小结一
--[[
ModuleName :EventManager
Path : LuaPractice\EventManager.lua
Author :CJBKing
CreateTime :2019-11-11 18:17:08
Description :
--]]
GlobalListenerMap={
--[[
[target]={
[type#key]=listenerList,
}
--]]
}
local clsEvent={}
function clsEvent.Create(target,type,key,data)
local o={
target,
type,
key,
data,
}
setmetatable(o,{__index=clsEvent})
return o
end
function clsEvent:GetTarget() return self[1] end
function clsEvent:GetType() return self[2] end
function clsEvent:GetKey() return self[3] end
function clsEvent:GetData() return self[4] end
-----------------------------------------------------------------
function GenListenerId()
local nextListenerId=0
return function()
nextListenerId=nextListenerId+1
return nextListenerId
end
end
local genListenerId=GenListenerId()
local cacheEventTypeKey={
--[eventType]={_KeyCnt=0,_KeyValue={[key]="eventType#Key"}}
}
-----这里当cacheEventTypeKey的某个eventType达到一定数时,会重置
-----比如EVENT_REMOVE_ENTITY的key是entityID,是动态变化的,这种类型的key随着程序的运行会很大
function GenIndex(eventType,key)
local eventTypeMap=cacheEventTypeKey[eventType]
local fEventType=tostring(eventType)
local fKey=tostring(key)
if not eventTypeMap then
local f=string.format("%s#%s",fEventType,fKey)
local keyValue={}
keyValue[fKey]=f
eventTypeMap={}
eventTypeMap._KeyCnt=1 --计数
eventTypeMap._KeyValue=keyValue
cacheEventTypeKey[fEventType]=eventTypeMap
return f
end
local keyValue= eventTypeMap._KeyValue
local f=keyValue[fKey]
if f then
return f
end
local keyCnt=eventTypeMap._KeyCnt+1
if keyCnt>1000 then --如果事件类型大于1000
keyValue={}
eventTypeMap._KeyValue=keyValue
keyCnt=1
end
f=string.format("%s#%s",fEventType,fKey)
keyValue[fKey]=f
eventTypeMap._KeyCnt=keyCnt
eventTypeMap._KeyValue=keyValue
print(cacheEventTypeKey._KeyCnt)
return f
end
function GetSubTableWithDefault(target,key)
local value=target[key]
if not value then
value={}
target[key]=value
end
return value
end
local clsListener={}
function clsListener.Create(Observer,Target,Type,Key,CallBack)
local OId=genListenerId()
local typeIndex=GenIndex(Type,Key)
local listener={
Observer,
Target,
Type,
Key,
CallBack,
OId,
typeIndex,
}
setmetatable(listener,{__index=clsListener})
local typeListenerMap=GetSubTableWithDefault(GlobalListenerMap,Target)
local listenerList=GetSubTableWithDefault(typeListenerMap,typeIndex)
table.insert(listenerList,listener)
if type(Observer)=="table" then
local objListenerMap=GetSubTableWithDefault(Observer,"__eventListenerMap")
objListenerMap[OId]=listener
end
return listener
end
function clsListener:GetObserver() return self[1] end
function clsListener:GetTarget() return self[2] end
function clsListener:GetType() return self[3] end
function clsListener:GetKey() return self[4] end
function clsListener:GetCallBack() return self[5] end
function clsListener:GetOId() return self[6] end
function clsListener:Handle(event)
local callback=self:GetCallBack()
callback(event)
-- xpcall(callback,TracBack,event)
end
function clsListener:Remove()
local typeIndex = self[7]
if not typeIndex then
----print("can not here.......")
return
end
self[7] = nil
local observer = self:GetObserver()
if IsTable(observer) then
local OId = self:GetOId()
observer.__eventListenerMap[OId] = nil
end
local target = self:GetTarget()
local typeListenerMap = GlobalListenerMap[target]
if not typeListenerMap then
return
end
local listenerList = typeListenerMap[typeIndex]
local len = #listenerList
if len == 1 and listenerList[1] == self then
listenerList[1] = nil
typeListenerMap[typeIndex] = nil
if table.next(typeListenerMap) then
GlobalListenerMap[target] = nil
end
else
--local key = table.member_key(listenerList, self) --- O(N)
local key=nil
for k,v in pairs(listenerList) do
if v==self then
key=k
end
end
if key then
----使用最后一个元素覆盖并删除最后一个元素
listenerList[key] = listenerList[len]
listenerList[len] = nil
end
end
end
function TracBack(msg,level)
-- print(msg,level)
end
function AddEventListener(observer, target, type, key, callback)
return clsListener.Create(observer, target, type, key, callback)
end
function RemoveListener(listener)
if listener then
listener:Remmove()
end
end
function RemoveEventListenerByType(observe,target,type,key)
local typeListenerMap=GlobalListenerMap[target]
if not typeListenerMap then
return
end
local typeIndex=GenIndex(type,key)
local listenerList=typeListenerMap[typeIndex]
if not listener then
return
end
local toDelListener = {}
for _,listener in pairs(listenerList) do
if listener:GetObserver()==observe then
table.insert(toDelListener,listener)
end
end
for _,listener in ipairs(toDelListener) do
listener:Remove()
end
end
function Dispatch(target, type, key, data)
local targetListenerMap = GlobalListenerMap[target]
if targetListenerMap then
local allListenerList = nil
local listenerList = targetListenerMap[GenIndex(type, key)]
if listenerList then
allListenerList = {}
for _, listener in ipairs(listenerList) do
table.insert(allListenerList, listener)
end
end
if allListenerList then
local event = clsEvent.Create(target, type, key, data)
for _, listener in ipairs(allListenerList) do
listener:Handle(event)
end
end
end
end
---------------测试--------------------------
local targetTest = {}
local function TestCallback(event)
print(event:GetData())
end
-- for i=1,2000 do
-- AddEventListener(nil,TestModule,"Test","TestOne" .. i,TestCallback)
-- Dispatch(TestModule,"Test","TestOne" .. i,"this is Data"..i)
-- end
local TestModule=loadfile("E:/LuaProject/LuaPractice/Test.lua")()
--if TestModule then TestModule() else print("testModule is not Exist") end
AddEventListener(TestModule,TestModule,"Test","TestOne",TestModule.FuncCallBack)
Dispatch(TestModule,"Test","TestOne","this is Data")