I have implemented abstract generic provider for notification bunch of generic listeners E
, descendants have to override notifyListener(E)
with specific notification code. For backing list of listeners I choose WeakHashMap<K,V>
. Listeners must be held as weak references:
abstract public class NotificationProvider<E> {
private Map<E, Object> listeners = new WeakHashMap<E, Object>();
public addListener(E listener) {
listeners.put(listener, null);
}
public void notifyListeners() {
for (E listener: listeners.keySet())
notifyListener(listener);
}
abstract protected void notifyListener(E listener);
}
Typical use:
NotificationProvider<MyListener> provider;
provider = new NotificationProvider<MyListener>() {
@Override
protected void notifyListener(MyListener listener) {
listener.myNotification();
}
}
provider.addListener(myListener1);
provider.addListener(myListener2);
provider.notifyListeners();
Everything works well, but when I need AbstractList
descendant class as listener, backing WeakHashMap
accepts only one listener instance! It's clear -- methods hashCode()
and equals()
on listeners return same value for all of instances (empty lists), so WeakHashMap.put
only replace previously added listener.
public class MyList extends AbstractList<MyItem> {
// some implementation
}
NotificationProvider<MyList> provider;
provider = new NotificationProvider<MyList>() {
@Override
protected void notifyListener(MyList listener) {
// some implementation
}
}
MyList list1 = new MyList();
MyList list2 = new MyList();
provider.addListener(list1);
provider.addListener(list2);
provider.notifyListeners(); // only list2 instance is notified
What is the best solution?
use another non-hashCode backing collection -- but
WeakHashMap
is so sweet for me, because automatically managing weak references for meuse non-generic listener, for example abstract class with simple
equals() { return (this == object); }
implementation -- but this is not so flexibleuse some wrapper for listeners with simple equals() -- but this wrapper cannot be transparent to
addListener(E)
caller due to weak references
Another ideas?