ListenerList - a Better Way to Manage Your Event Listeners
Join the DZone community and get the full member experience.
Join For FreeYou have published a listener interface and have a place where your clients register their listeners. There you typically code like this:
List<SomeEventListener> listeners = new ArrayList<SomeEventListener>(); public void addSomeEventListener(SomeEventListener listener) { listeners.add(listener); } public void removeSomeEventListener(SomeEventListener listener) { listeners.remove(listener); } public void fireSomeEvent(SomeEvent event) { for (SomeEventListener listener : listeners) { listener.eventOccured(event); } }
The problem with this approach is two fold:
- Memory usage: The capacity of the ArrayList is always >= its size. So if you just have 200 listeners, there is a good chance that the memory might have been allocated for 300 elements
- Thread safety: Murphy's law will prove itself, and multi threaded bugs can be a pain in your back to debug. You have to properly sync all the write access and provide faster read only access for event firing operations.
To handle these two issues, Eclipse gives you a nice API: ListenerList class. Its meant for storing these kind of listeners, where any write modification to the underlying array (add, remove, clear) is synchronized and give access to the underlying array for faster read access. Memory is allocated only for the number of listeners registered.
The same above example can be rewritten as:
ListenerList listeners = new ListenerList(); public void addSomeEventListener(SomeEventListener listener) { listeners.add(listener); } public void removeSomeEventListener(SomeEventListener listener) { listeners.remove(listener); } public void fireSomeEvent(SomeEvent event) { Object[] listenersArray = listeners.getListeners(); for (int i = 0; i < listenersArray.length; i++) { ((SomeEventListener)listenersArray[i]).eventOccured(event); } }
ListenerList provides two ways of duplicate checking of the listeners: Equality and Identity. It can be specified in the constructor. Since the core Eclipse platform is in Java 1.4, you still can't use generics and foreach, but that shouldn't be a hindrance.
Question: Now that I do have a direct access to the underlying array, what if i manipulate it like this:
Object[] listenersArray = listeners.getListeners(); listenersArray[0] = null; listenersArray[1] = someEventListener5;
Well, the same thing happens when you shoot yourself in the foot :-)
Opinions expressed by DZone contributors are their own.
Comments