--[[
ModuleName :EventManager
Path : LuaPractice\EventManager.lua
Author :CJBKing
CreateTime :2019-11-1118: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
-----------------------------------------------------------------functionGenListenerId()
local nextListenerId=0returnfunction()
nextListenerId=nextListenerId+1return nextListenerId
end
end
local genListenerId=GenListenerId()
local cacheEventTypeKey={--[eventType]={_KeyCnt=0,_KeyValue={[key]="eventType#Key"}}}-----这里当cacheEventTypeKey的某个eventType达到一定数时,会重置
-----比如EVENT_REMOVE_ENTITY的key是entityID,是动态变化的,这种类型的key随着程序的运行会很大
functionGenIndex(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+1if 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
functionGetSubTableWithDefault(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)iftype(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()ifIsTable(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 inpairs(listenerList)doif v==self then
key=k
end
end
if key then
----使用最后一个元素覆盖并删除最后一个元素
listenerList[key]= listenerList[len]
listenerList[len]= nil
end
end
end
functionTracBack(msg,level)--print(msg,level)
end
functionAddEventListener(observer, target, type, key, callback)return clsListener.Create(observer, target, type, key, callback)
end
functionRemoveListener(listener)if listener then
listener:Remmove()
end
end
functionRemoveEventListenerByType(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 inpairs(listenerList)doif listener:GetObserver()==observe then
table.insert(toDelListener,listener)
end
end
for _,listener inipairs(toDelListener)do
listener:Remove()
end
end
functionDispatch(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 inipairs(listenerList)do
table.insert(allListenerList, listener)
end
end
if allListenerList then
local event = clsEvent.Create(target, type, key, data)for _, listener inipairs(allListenerList)do
listener:Handle(event)
end
end
end
end
---------------测试--------------------------
local targetTest ={}
local functionTestCallback(event)print(event:GetData())
end
--for i=1,2000do--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()elseprint("testModule is not Exist") end
AddEventListener(TestModule,TestModule,"Test","TestOne",TestModule.FuncCallBack)Dispatch(TestModule,"Test","TestOne","this is Data")