|
|||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object org.openide.util.WeakListeners
A generic weak listener factory.
Creates a weak implementation of a listener of type lType
.
In the following examples, I'll use following naming:
There are four objects involved in weak listener usage:
*Listener
interface, sometimes the observer itself but
often some observer's inner class delegating the events to the observer.
Utilities
have factory methods for the most common listeners used in NetBeans
and also one universal factory method you can use for other listeners.
public class ListenerObserver implements ChangeListener {
private void registerTo(Source source) {
source.addChangeListener(WeakListeners.changeListener
(this, source));
}
public void stateChanged(ChangeEvent e) {
doSomething();
}
}
You can also factor out the listener implementation to some other class
if you don't want to expose the stateChanged method (better technique):
public class Observer {
private Listener listener;
private void registerTo(Source source) {
listener = new Listener();
source.addChangeListener(WeakListeners.change
(listener, source));
}
private class Listener implements ChangeListener {
public void stateChanged(ChangeEvent e) {
doSomething();
}
}
}
Note: The observer keeps the reference to the listener, it won't work
otherwise, see below.
You can also use the universal factory for other listeners:
public class Observer implements SomeListener {
private void registerTo(Source source) {
source.addSomeListener((SomeListener)WeakListeners.create
(
SomeListener.class, this, source));
}
public void someEventHappened(SomeEvent e) {
doSomething();
}
}
public class Observer { private void registerTo(Source source) { source.addChangeListener(WeakListeners.change(new Listener(), source)); } private class Listener implements ChangeListener { public void stateChanged(ChangeEvent e) { doSomething(); } } }Mistake: There is nobody holding strong reference to the Listener instance, so it may be freed on the next GC cycle.
public class ListenerObserver implements ChangeListener { private void registerTo(Source source) { source.addChangeListener(WeakListeners.change(this, null)); } public void stateChanged(ChangeEvent e) { doSomething(); } }Mistake: The weak listener is unable to unregister itself from the source once the listener is freed. For explanation, read below.
The weak listener is used as a reference-weakening wrapper
around the listener. It is itself strongly referenced from the implementation
of the source (e.g. from its EventListenerList
) but it references
the listener only through WeakReference
. It also weak-references
the source. Listener, on the other hand, usually strongly references
the observer (typically through the outer class reference).
This means that:
WeakListeners.change(new MyListener(), ..)
as the only reference
to the listener will be the weak one from the weak listener.
Now what happens when the listener/observer is removed from memory:
remove<listenerType>
of the source and calling it.
This may fail if the source don't have the expected remove*
method and/or if you provide wrong reference to source. In that case
the weak listener instance will stay in memory and registered by the source,
while the listener and observer will be freed.
There is still one fallback method - if some event come to a weak listener and the listener is already freed, the weak listener tries to unregister itself from the object the event came from.
Method Summary | |
static ChangeListener |
change(ChangeListener l,
Object source)
Creates a weak implementation of ChangeListener. |
static EventListener |
create(Class lType,
Class apiType,
EventListener l,
Object source)
The most generic factory method to create weak listener for any listener interface that moreover behaves like a listener of another type. |
static EventListener |
create(Class lType,
EventListener l,
Object source)
Generic factory method to create weak listener for any listener interface. |
static DocumentListener |
document(DocumentListener l,
Object source)
Creates a weak implementation of DocumentListener. |
static PropertyChangeListener |
propertyChange(PropertyChangeListener l,
Object source)
Creates a weak implementation of PropertyChangeListener. |
static VetoableChangeListener |
vetoableChange(VetoableChangeListener l,
Object source)
Creates a weak implementation of VetoableChangeListener. |
Methods inherited from class java.lang.Object |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Method Detail |
public static EventListener create(Class lType, EventListener l, Object source)
lType
- the type of listener to create. It can be any interface,
but only interfaces are allowed.l
- the listener to delegate to, l
must be an instance
of lType
source
- the source that the listener should detach from when
listener l
is freed, can be null
lType
delegating all the interface
calls to l
.public static EventListener create(Class lType, Class apiType, EventListener l, Object source)
For example EventContext
allows to add an
instance of ObjectChangeListener
but using
method addNamingListener
. Method removeNamingListener
is then used to remove it. To help the weak listener support to correctly
find the right method one have to use:
ObjectChangeListener l = (ObjectChangeListener)WeakListeners.create ( ObjectChangeListener.class, // the actual class of the returned listener NamingListener.class, // but it always will be used as NamingListener yourObjectListener, someContext ); someContext.addNamingListener ("", 0, l);This will correctly create
ObjectChangeListener
and unregister it by
calling removeNamingListener
.
lType
- the type the listener shall implement. It can be any interface,
but only interfaces are allowed.apiType
- the interface the returned object will be used as. It
shall be equal to lType
or its superinterfacel
- the listener to delegate to, l
must be an instance
of lType
source
- the source that the listener should detach from when
listener l
is freed, can be null
lType
delegating all the interface
calls to l
.public static PropertyChangeListener propertyChange(PropertyChangeListener l, Object source)
l
- the listener to delegate tosource
- the source that the listener should detach from when
listener l
is freed, can be null
l
.public static VetoableChangeListener vetoableChange(VetoableChangeListener l, Object source)
l
- the listener to delegate tosource
- the source that the listener should detach from when
listener l
is freed, can be null
l
.public static DocumentListener document(DocumentListener l, Object source)
l
- the listener to delegate tosource
- the source that the listener should detach from when
listener l
is freed, can be null
l
.public static ChangeListener change(ChangeListener l, Object source)
l
- the listener to delegate tosource
- the source that the listener should detach from when
listener l
is freed, can be null
l
.
|
|||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |