title: Custom Observable List implementation, notifying consumers of changes
body: <p>I have created a custom ObservableList implementation for a list of TreeItems. My custom implementation can listen to various notifications from inside my app (using OSGi EventAdmin), and update itself accordingly. I then expect its consumer (a TreeView widget) to be updated with the changes to the list. However, I can't see how to notify the consumer.</p>
  
  <p>In the ObservableList subclass I am implementing addListener(ListChangeListener), which I would expect to get called when the object is added to the widget. However it is never called; I have no listeners thus no apparent way to notify anyone when the list changes. I must be missing something.</p>
  
  <p>Here is a snippet from my TreeItem implementation, which returns an instance of my ObservableList in response to a getChildren call:</p>
  
  <pre><code>    @Override
      public ObservableList&lt;TreeItem&lt;DataObject&gt;&gt; getChildren() {
          if (needChildren) {
              needChildren = false;
              children = new MyObservableList();
          }
          return children;
      }
  </code></pre>
  
  <p>Here is an abridged version of my custom ObservableList implementation, which simply wraps an FXCollections.observableArrayList and adds an OSGi event handler. I listen to changes on the internal list so that I can pass those changes on to my listeners.</p>
  
  <pre><code>    public class MyObservableList implements ObservableList&lt;TreeItem&lt;DataObject&gt;&gt;, EventHandler {
      private List&lt;ListChangeListener&lt;? super TreeItem&lt;DataObject&gt;&gt;&gt; changeListeners = new ArrayList&lt;&gt;();
      private List&lt;InvalidationListener&gt; invalidationListeners = new ArrayList&lt;&gt;();
      private ObservableList&lt;TreeItem&lt;DataObject&gt;&gt; theList;
      private int size;
  
      public MyObservableList() {
          theList = FXCollections.observableArrayList();
  
          theList.addListener(new ListChangeListener&lt;TreeItem&lt;DataObject&gt;&gt;() {
              @Override
              public void onChanged(Change&lt;? extends TreeItem&lt;DataObject&gt;&gt; change) {
                  fireValueChangedEvent(change);
              }
          });
      }
  
      @Override
      public int size() {
          return theList.size();
      }
  
      @Override
      public boolean isEmpty() {
          return (size == 0);
      }
  
      @Override
      public boolean contains(Object o) {
          return theList.contains(o);
      }
  
      @Override
      public Iterator iterator() {
          return theList.iterator();
      }
  
      @Override
      public boolean remove(Object o) {
          return theList.remove(o);
      }
  
      @Override
      public boolean addAll(Collection c) {
          return theList.addAll(c);
      }
  
      @Override
      public boolean addAll(int index, Collection c) {
          return theList.addAll(index, c);
      }
  
  
      @Override
      public void clear() {
          theList.clear();
      }
  
      @Override
      public TreeItem&lt;DataObject&gt; get(int index) {
          return theList.get(index);
      }
  
      @Override
      public int indexOf(Object o) {
          return theList.indexOf(o);
      }
  
      @Override
      public int lastIndexOf(Object o) {
          return theList.lastIndexOf(o);
      }
  
      @Override
      public ListIterator listIterator() {
          return theList.listIterator();
      }
  
      @Override
      public ListIterator listIterator(int index) {
          return theList.listIterator(index);
      }
  
  
      @Override
      public List&lt;TreeItem&lt;DataObject&gt;&gt; subList(int fromIndex, int toIndex) {
          return theList.subList(fromIndex, toIndex);
      }
  
      @Override
      public Object[] toArray(Object[] a) {
          return theList.toArray(a);
      }
  
      @Override
      public void addListener(ListChangeListener&lt;? super TreeItem&lt;DataObject&gt;&gt; listChangeListener) {
          changeListeners.add(listChangeListener);
      }
  
      @Override
      public void removeListener(ListChangeListener&lt;? super TreeItem&lt;DataObject&gt;&gt; listChangeListener) {
          changeListeners.remove(listChangeListener);
      }
  
      @Override
      public boolean addAll(TreeItem&lt;DataObject&gt;... treeItems) {
          return theList.addAll(treeItems);
      }
  
      @Override
      public boolean setAll(TreeItem&lt;DataObject&gt;... treeItems) {
          return theList.setAll(treeItems);
      }
  
      @Override
      public boolean setAll(Collection&lt;? extends TreeItem&lt;DataObject&gt;&gt; treeItems) {
          return theList.setAll(treeItems);
      }
  
      @Override
      public boolean removeAll(TreeItem&lt;DataObject&gt;... treeItems) {
          return theList.removeAll(treeItems);
      }
  
      @Override
      public boolean retainAll(TreeItem&lt;DataObject&gt;... treeItems) {
          return theList.retainAll(treeItems);
      }
  
      @Override
      public void remove(int i, int i2) {
          theList.remove(i, i2);
      }
  
      @Override
      public Object[] toArray() {
          return theList.toArray();
      }
  
      @Override
      public boolean add(TreeItem&lt;DataObject&gt; dataObjectTreeItem) {
          return theList.add(dataObjectTreeItem);
      }
  
      @Override
      public boolean containsAll(Collection&lt;?&gt; c) {
          return theList.containsAll(c);
      }
  
      @Override
      public boolean removeAll(Collection&lt;?&gt; c) {
          return theList.removeAll(c);
      }
  
      @Override
      public boolean retainAll(Collection&lt;?&gt; c) {
          return theList.retainAll(c);
      }
  
      @Override
      public TreeItem&lt;DataObject&gt; set(int index, TreeItem&lt;DataObject&gt; element) {
          return theList.set(index, element);
      }
  
      @Override
      public void add(int index, TreeItem&lt;DataObject&gt; element) {
          theList.add(index, element);
      }
  
      @Override
      public TreeItem&lt;DataObject&gt; remove(int index) {
          return theList.remove(index);
      }
  
      @Override
      public void addListener(InvalidationListener invalidationListener) {
          invalidationListeners.add(invalidationListener);
      }
  
      @Override
      public void removeListener(InvalidationListener invalidationListener) {
          invalidationListeners.remove(invalidationListener);
      }
  
      private void fireValueChangedEvent(ListChangeListener.Change&lt;? extends TreeItem&lt;DataObject&gt;&gt; change) {
          for (ListChangeListener&lt;? super TreeItem&lt;DataObject&gt;&gt; listener : changeListeners) {
              listener.onChanged(change);
          }
      }
  
      @Override
      public void handleEvent(Event event) {
          // Here I add or remove TreeItem&lt;DataObject&gt; instances to the list based on event.
          //
          // At this point, onChanged() gets called above in my listener, but my changeListeners list is empty. There is
          // no one to pass the Change on to.
      }
  }
  </code></pre>
  
  <p>Thanks for any help.</p>