I’m a little puzzled over something. Java’s documentation tells us that there is no defined behavior when removing items from a collection while iterating over that collection using an Iterator object and that the only safe way to do so is to use Iterator.remove().
How then, would you safely remove an event handler from an ArrayList if, in the course of iterating through the list one of the handlers has decided that it’s time to remove itself as a listener?
// in public class Dispatcher
public void dispatchEvent(){
Iterator<IEventHandler> iterator = mHandlers.iterator();
IEventHandler handler = null;
while(iterator.hasNext()){
handler = iterator.next();
handler.onCallbackEvent();
}
}
public void insertHandler(IEventHandler h){
mHandlers.add(h);
}
public void removeHandler(IEventHandler h){
mHandlers.remove(h);
}
Meanwhile, the handler was instantiated like this…
final Dispatcher d = new Dispatcher();
d.insertHandler(new IEventHandler(){
@Override
public void onCallbackEvent(){
Log.i(" callback happened ");
d.removeHandler(this);
}
});
See the potential problem? You’re removing the handler from the ArrayList as a result of the onCallbackEvent() declared in that specific handler while you’re still iterating using the Iterator.
Is this an intractable problem? What’s the safe way to handle this situation?
This is a very common problem when implementing an event system. The only solution is to copy the list of handlers on change. You can do this yourself in the insertHandler/removeHandler methods or just use CopyOnWriteArrayList.