package dan.dit.whatsthat.util.general; import java.util.ArrayList; import java.util.List; /** * A robust implementation of a controller of a list of observers. The observers can be added and * removed at any time (event during event processing). Processing an event can trigger other * events. Adding and removing observers will only take place after all processing is done. So * removing an observer during processing an event will not prevent it from being called in case * another event is triggered during processing. Processed events that result in nested * notifications must do this in the original thread of the first notification, this also * includes adding and removing of observers as these operations are synchronized. * Created by daniel on 26.11.15. */ public class RobustObserverController<Observer extends ObserverController.Observer<? super Event>, Event> extends ObserverController<Observer, Event> { private List<Observer> mAddedObservers = new ArrayList<>(4); private List<Observer> mRemovedObservers = new ArrayList<>(4); private int mIsProcessingEventDepth; @Override public synchronized void addObserver(Observer observer) { if (observer != null && !mObservers.contains(observer) && !mAddedObservers.contains(observer)) { mAddedObservers.add(observer); } } @Override public synchronized boolean removeObserver(Observer observer) { if (mObservers.contains(observer) && !mRemovedObservers.contains(observer)) { mRemovedObservers.add(observer); return true; } return false; } @Override public synchronized void notifyObservers(Event event) { if (mIsProcessingEventDepth == 0) { for (int i = 0; i < mAddedObservers.size(); i++) { mObservers.add(mAddedObservers.get(i)); } for (int i = 0; i < mRemovedObservers.size(); i++) { mObservers.remove(mRemovedObservers.get(i)); } mAddedObservers.clear(); mRemovedObservers.clear(); } mIsProcessingEventDepth++; super.notifyObservers(event); mIsProcessingEventDepth--; } }