|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun * Microsystems, Inc. All Rights Reserved. */ package org.openide.util; import java.awt.event.FocusListener; import java.beans.PropertyChangeListener; import java.beans.VetoableChangeListener; import java.util.EventListener; import javax.swing.event.ChangeListener; import javax.swing.event.DocumentListener; /** A generic weak listener factory. * Creates a weak implementation of a listener of type
Utilities
* have factory methods for the most common listeners used in NetBeans
* and also one universal factory method you can use for other listeners.
*
* How to use it:* Here is an example how to write a listener/observer and make it listen * on some source: ** public class ListenerObserver implements ChangeListener { * private void registerTo(Source source) { * source.addChangeListener({@link #change(javax.swing.event.ChangeListener, java.lang.Object) * 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({@link #change(javax.swing.event.ChangeListener, java.lang.Object) * 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){@link * #create(java.lang.Class, java.util.EventListener, java.lang.Object) * WeakListeners.create} ( * SomeListener.class, this, source)); * } * * public void someEventHappened(SomeEvent e) { * doSomething(); * } * } ** * How to not use it:* Here are examples of a common mistakes done when using weak listener: ** 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. * How does it work:*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
Now what happens when the listener/observer is removed from memory:
This may fail if the source don't have the expected 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.
*
* @since 4.10
*/
public final class WeakListeners {
/** No instances.
*/
private WeakListeners () {
}
/** Generic factory method to create weak listener for any listener
* interface.
*
* @param lType the type of listener to create. It can be any interface,
* but only interfaces are allowed.
* @param l the listener to delegate to,
* For example {@link javax.naming.event.EventContext} allows to add an
* instance of {@link javax.naming.event.ObjectChangeListener} but using
* method * 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 .
*
* @param lType the type the listener shall implement. It can be any interface,
* but only interfaces are allowed.
* @param apiType the interface the returned object will be used as. It
* shall be equal to lType or its superinterface
* @param l the listener to delegate to, l must be an instance
* of lType
* @param source the source that the listener should detach from when
* listener l is freed, can be null
* @return an instance of lType delegating all the interface
* calls to l .
* @since 4.12
*/
public static EventListener create (Class lType, Class apiType, EventListener l, Object source) {
if (!lType.isInterface()) {
throw new IllegalArgumentException ("Not interface: " + lType);
}
if (!apiType.isInterface()) {
throw new IllegalArgumentException ("Not interface: " + apiType);
}
if (!apiType.isAssignableFrom(lType)) {
throw new IllegalArgumentException (apiType + " has to be assignableFrom " + lType); // NOI18N
}
return WeakListenerImpl.create (lType, apiType, l, source);
}
/** Creates a weak implementation of PropertyChangeListener.
*
* @param l the listener to delegate to
* @param source the source that the listener should detach from when
* listener l is freed, can be null
* @return a PropertyChangeListener delegating to l .
*/
public static PropertyChangeListener propertyChange (PropertyChangeListener l, Object source) {
WeakListenerImpl.PropertyChange wl = new WeakListenerImpl.PropertyChange (l);
wl.setSource (source);
return wl;
}
/** Creates a weak implementation of VetoableChangeListener.
*
* @param l the listener to delegate to
* @param source the source that the listener should detach from when
* listener l is freed, can be null
* @return a VetoableChangeListener delegating to l .
*/
public static VetoableChangeListener vetoableChange (VetoableChangeListener l, Object source) {
WeakListenerImpl.VetoableChange wl = new WeakListenerImpl.VetoableChange (l);
wl.setSource (source);
return wl;
}
/** Creates a weak implementation of DocumentListener.
*
* @param l the listener to delegate to
* @param source the source that the listener should detach from when
* listener l is freed, can be null
* @return a DocumentListener delegating to l .
*/
public static DocumentListener document (DocumentListener l, Object source) {
WeakListenerImpl.Document wl = new WeakListenerImpl.Document (l);
wl.setSource (source);
return wl;
}
/** Creates a weak implementation of ChangeListener.
*
* @param l the listener to delegate to
* @param source the source that the listener should detach from when
* listener l is freed, can be null
* @return a ChangeListener delegating to l .
*/
public static ChangeListener change (ChangeListener l, Object source) {
WeakListenerImpl.Change wl = new WeakListenerImpl.Change (l);
wl.setSource (source);
return wl;
}
}
|
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.