Overview | Package | Class | Use | Tree | Deprecated | Index | Help
| org.openide.util 6.8.22
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

## org.openide.util
Class WeakListeners

    java.lang.Object
      org.openide.util.WeakListeners

    public final class WeakListeners

extends Object

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:

- The event source object
- The observer - object that wants to listen on source
- The listener - the implementation of the corresponding `*Listener` interface, sometimes the observer itself but often some observer's inner class delegating the events to the observer.
- The weak listener implementation.

The examples are written for ChangeListener. The `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(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();
          }
      }

## 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 `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:

1. If the listener is not strong-referenced from elsewhere, it can be thrown away on the next GC cycle. This is why you can't use `WeakListeners.change(new MyListener(), ..)` as the only reference to the listener will be the weak one from the weak listener.
2. If the listener-observer pair is not strong-referenced from elsewhere it can be thrown away on the next GC cycle. This is what the weak listener was invented for.
3. If the source is not strong-referenced from anywhere, it can be thrown away on the next GC cycle taking the weak listener with it, but not the listener and the observer if they are still strong-referenced (unusual case, but possible).

Now what happens when the listener/observer is removed from memory:

- The weak listener is notified that the reference to the listener was cleared.
- It tries to unregister itself from the source. This is why it needs the reference to the source for the registration. The unregistration is done using reflection, usually looking up the method `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.

Since:
  4.10

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

### create

    public static EventListener create(Class lType,
                                       EventListener l,
                                       Object source)

  Generic factory method to create weak listener for any listener interface.

  Parameters:
    `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`
  Returns:
    an instance of `lType` delegating all the interface calls to `l`.

### create

    public 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. This can be useful to correctly remove listeners from a source when hierarchies of listeners are used.

  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`.

  Parameters:
    `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 superinterface
    `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`
  Returns:
    an instance of `lType` delegating all the interface calls to `l`.
  Since:
    4.12

### propertyChange

    public static PropertyChangeListener propertyChange(PropertyChangeListener l,
                                                        Object source)

  Creates a weak implementation of PropertyChangeListener.

  Parameters:
    `l` - the listener to delegate to
    `source` - the source that the listener should detach from when listener `l` is freed, can be `null`
  Returns:
    a PropertyChangeListener delegating to `l`.

### vetoableChange

    public static VetoableChangeListener vetoableChange(VetoableChangeListener l,
                                                        Object source)

  Creates a weak implementation of VetoableChangeListener.

  Parameters:
    `l` - the listener to delegate to
    `source` - the source that the listener should detach from when listener `l` is freed, can be `null`
  Returns:
    a VetoableChangeListener delegating to `l`.

### document

    public static DocumentListener document(DocumentListener l,
                                            Object source)

  Creates a weak implementation of DocumentListener.

  Parameters:
    `l` - the listener to delegate to
    `source` - the source that the listener should detach from when listener `l` is freed, can be `null`
  Returns:
    a DocumentListener delegating to `l`.

### change

    public static ChangeListener change(ChangeListener l,
                                        Object source)

  Creates a weak implementation of ChangeListener.

  Parameters:
    `l` - the listener to delegate to
    `source` - the source that the listener should detach from when listener `l` is freed, can be `null`
  Returns:
    a ChangeListener delegating to `l`.

Overview | Package | Class | Use | Tree | Deprecated | Index | Help
| org.openide.util 6.8.22
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

Built on December 7 2006. | Portions Copyright 1997-2005 Sun Microsystems, Inc. All rights reserved.