[dispatcher] Removing unused listeners after dispatching event.

This commit is contained in:
James Chen 2013-09-12 20:45:35 +08:00
parent fb12c90238
commit 06bc92ff19
3 changed files with 140 additions and 45 deletions

View File

@ -29,7 +29,6 @@ NS_CC_BEGIN
Event::Event(const std::string& type)
: _type(type)
, _isStopped(false)
, _isValid(true)
{
}

View File

@ -239,34 +239,20 @@ void EventDispatcher::dispatchEvent(Event* event)
(*listenerIter)->listener->onEvent(event);
if ((*listenerIter)->id == 0)
{
delete (*listenerIter);
listenerList->remove(*listenerIter);
}
if (event->isStopped())
break;
}
if (listenerList->empty())
{
_listeners->erase(iter);
CC_SAFE_DELETE(listenerList);
}
}
if (_listeners->empty())
{
CC_SAFE_DELETE(_listeners);
}
}
removeUnregisteredListeners();
}
void EventDispatcher::dispatchTouchEvent(TouchEvent* event)
{
auto touchListeners = getListeners(TouchEvent::EVENT_TYPE);
if (touchListeners == nullptr)
return;
std::vector<EventDispatcher::EventListenerItem*> oneByOnelisteners;
oneByOnelisteners.reserve(touchListeners->size());
@ -313,6 +299,10 @@ void EventDispatcher::dispatchTouchEvent(TouchEvent* event)
auto oneByOneIter = oneByOnelisteners.begin();
for (; oneByOneIter != oneByOnelisteners.end(); ++oneByOneIter)
{
// Skip if the listener was removed.
if ((*oneByOneIter)->id == 0)
continue;
bool isClaimed = false;
std::vector<Touch*>::iterator removedIter;
@ -363,6 +353,12 @@ void EventDispatcher::dispatchTouchEvent(TouchEvent* event)
}
}
// If the event was stopped, return directly.
if (event->isStopped())
{
removeUnregisteredListeners();
return;
}
CCASSERT((*touchesIter)->getID() == (*mutableTouchesIter)->getID(), "");
@ -425,12 +421,61 @@ void EventDispatcher::dispatchTouchEvent(TouchEvent* event)
CCASSERT(false, "The eventcode is invalid.");
break;
}
// If the event was stopped, return directly.
if (event->isStopped())
{
removeUnregisteredListeners();
return;
}
}
}
removeUnregisteredListeners();
}
void EventDispatcher::removeUnregisteredListeners()
{
if (!_listeners)
return;
auto listenerItemIter = _listeners->begin();
while ( listenerItemIter != _listeners->end())
{
auto removeIterBegin = std::remove_if(listenerItemIter->second->begin(), listenerItemIter->second->end(), [](const EventListenerItem* item){
return item->id == 0;
});
for (auto iter = removeIterBegin; iter != listenerItemIter->second->end(); ++iter)
{
delete (*iter);
}
listenerItemIter->second->erase(removeIterBegin, listenerItemIter->second->end());
if (listenerItemIter->second->empty())
{
delete listenerItemIter->second;
listenerItemIter = _listeners->erase(listenerItemIter);
}
else
{
++listenerItemIter;
}
}
if (_listeners->empty())
{
delete _listeners;
_listeners = nullptr;
}
}
void EventDispatcher::sortAllEventListenerItems()
{
if (_listeners == nullptr)
return;
for (auto listenerItemIter = _listeners->begin(); listenerItemIter != _listeners->end(); ++listenerItemIter)
{
// After sort: priority < 0, = 0, scene graph, > 0
@ -463,14 +508,59 @@ void EventDispatcher::sortAllEventListenerItems()
}
std::list<EventDispatcher::EventListenerItem*>* EventDispatcher::getListeners(const std::string& eventType)
{
if (_listeners != nullptr)
{
auto iter = _listeners->find(eventType);
if (iter != _listeners->end())
{
return iter->second;
}
}
return nullptr;
}
void EventDispatcher::removeListenersForEventType(const std::string& eventType)
{
if (_listeners == nullptr)
return;
auto listenerItemIter = _listeners->find(eventType);
if (listenerItemIter != _listeners->end())
{
for (auto iter = listenerItemIter->second->begin(); iter != listenerItemIter->second->end(); ++iter)
{
delete (*iter);
}
listenerItemIter->second->clear();
delete listenerItemIter->second;
_listeners->erase(listenerItemIter);
}
}
void EventDispatcher::removeAllListeners()
{
if (_listeners == nullptr)
return;
for (auto listenerItemIter = _listeners->begin(); listenerItemIter != _listeners->end(); ++listenerItemIter)
{
for (auto iter = listenerItemIter->second->begin(); iter != listenerItemIter->second->end(); ++iter)
{
delete (*iter);
}
listenerItemIter->second->clear();
delete listenerItemIter->second;
}
delete _listeners;
_listeners = nullptr;
}
NS_CC_END

View File

@ -51,14 +51,6 @@ dispatched.
class EventDispatcher
{
public:
struct EventListenerItem
{
int id;
Node* node; // Weak reference.
int fixedPriority; // The higher the number, the higher the priority
std::shared_ptr<EventListener> listener;
};
/** Gets the singleton of EventDispatcher */
static EventDispatcher* getInstance();
@ -72,7 +64,6 @@ public:
*/
int registerEventListenerWithFixedPriority(std::shared_ptr<EventListener> listener, int fixedPriority);
/** Unregisters a callback function by the unique ID. */
void unregisterEventListener(int listenerId);
@ -94,10 +85,25 @@ public:
*/
void dispatchEvent(Event* event);
/** Gets event listener list by event type. */
std::list<EventListenerItem*>* getListeners(const std::string& eventType);
/** Removes listeners by event type */
void removeListenersForEventType(const std::string& eventType);
/** Removes all listeners */
void removeAllListeners();
public:
/** Destructor of EventDispatcher */
~EventDispatcher();
private:
struct EventListenerItem
{
int id;
Node* node; // Weak reference.
int fixedPriority; // The higher the number, the higher the priority
std::shared_ptr<EventListener> listener;
};
/** Constructor of EventDispatcher */
EventDispatcher();
@ -106,15 +112,15 @@ private:
/** Touch event needs to be processed different with other events since it needs support ALL_AT_ONCE and ONE_BY_NONE mode. */
void dispatchTouchEvent(TouchEvent* event);
public:
/** Destructor of EventDispatcher */
~EventDispatcher();
private:
/** Gets event listener list by event type. */
std::list<EventListenerItem*>* getListeners(const std::string& eventType);
/** Sorts all listeners by priority */
void sortAllEventListenerItems();
/** Remove listeners that have been unregistered. */
void removeUnregisteredListeners();
private:
/**
* Listeners map.