Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8127736

ChangeListener sometimes misses changes, while InvalidationListener does not

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Incomplete
    • Icon: P4 P4
    • None
    • fx2.1, 7u6
    • javafx
    • JavaFX 2.1b19, 2.2b3

      I'm having a rather odd issue that I cannot debug any further.

      See code below, and notice I've written some "bind" methods that bind a property weakly (although the WeakInvalidationListener / WeakChangeListener have nothing to do with this bug, see below).

      Now, I wrote all this to work around another issue (TreeCell's lack of a dispose method in which to unbind things), and for some reason only the version that uses the InvalidationListener works correctly for all fields being monitored in this way. If I use the ChangeListener version, then one of the fields sometimes fails to update (even though print statements in my log clearly show I've updated them along with the other fields displayed in the same cell).

      The wierd thing is, this field is actually a calculation:
        hardRefs.add(WeakBindings.bindWeakly(cell.ratingProperty(), item.ratingProperty().divide(10));

      Now, if I remove that calculation part (the divide(10)) then both variants will always work, ChangeListener or InvalidationListener. With the divide(10), it will sometimes not work (some of the TreeCells are not properly updated). See the code below for how these weak bindings are implemented, what have I done wrong?

      Note that it also happens when I donot wrap the value in the WeakChangeListener at all, so it is not even related to weak bindings.


      package hs.mediasystem.util;

      import javafx.beans.InvalidationListener;
      import javafx.beans.Observable;
      import javafx.beans.WeakInvalidationListener;
      import javafx.beans.property.Property;
      import javafx.beans.value.ChangeListener;
      import javafx.beans.value.ObservableValue;
      import javafx.beans.value.WeakChangeListener;

      public class WeakBindings {
        public static <T> ChangeListener<T> bindWeaklyChange(final Property<T> property, final ObservableValue<? extends T> dest) {
          ChangeListener<T> changeListener = new ChangeListener<T>() {
            @Override
            public void changed(ObservableValue<? extends T> observableValue, T oldT, T newT) {
              property.setValue(newT);
            }
          };

          dest.addListener(new WeakChangeListener<>(changeListener));
          property.setValue(dest.getValue());

          return changeListener;
        }

        public static <T> InvalidationListener bindWeakly(final Property<T> property, final ObservableValue<? extends T> dest) {
          InvalidationListener invalidationListener = new InvalidationListener() {
            @Override
            public void invalidated(Observable observable) {
              property.setValue(dest.getValue());
            }
          };

          dest.addListener(new WeakInvalidationListener(invalidationListener));
          property.setValue(dest.getValue());

          return invalidationListener;
        }
      }

            mheinrichs Michael Heinrichs (Inactive)
            jhendrikx John Hendrikx
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported: