Why isn't this PropertyChangeListener working?

1k views Asked by At

I am working on adding support for property observations for my open source library droidQuery, however the propertyChange method is not being called in my tests. What do I need to do to get this to work? Here is my code:

ViewObserver.java

package self.philbrown.droidQuery;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import android.view.View;

/**
 * Provides Property Change Listening to simulate bindings
 * @author Phil Brown
 *
 */
public class ViewObserver implements PropertyChangeListener
{

    /** The function to call when the interface's method is invoked. */
    private Function function;

    /**
     * Constructor
     * @param droidQuery an instance of droidQuery
     * @param function the function to call when the value changes. Will include a {@link Observation}
     * Object with information about the KVO operation.
     */
    public ViewObserver(Function function)
    {
        this.function = function;
    }


    @Override
    public void propertyChange(PropertyChangeEvent event) //<-- This is never reached!
    {
        Observation observation = new Observation(event);
        function.invoke($.with((View) event.getSource()), observation);
    }

    /**
     * Represents an observation event that occured.
     */
    public static class Observation
    {
        /** The old value prior the this Observation */
        public Object oldValue;
        /** The new value */
        public Object newValue;
        /** The name of the property that has changed from {@code oldValue} to {@code newValue}. */
        public String property;

        /**
         * Constructor. Private since it is only used locally.
         * @param event
         */
        private Observation(PropertyChangeEvent event)
        {
            oldValue = event.getOldValue();
            newValue = event.getNewValue();
            property = event.getPropertyName();
        }
    }

}

Relevant portions of droidQuery.java (the rest available on github):

/** Used for Property Change Listening to simulate KVO Binding in droidQuery */
private static Map<View, Map<String, WeakReference<Observer>>> observers;

//The constructor has this:
//if (observers == null)
//    observers = new HashMap<View, Map<String, WeakReference<Observer>>>();


    /**
     * Observe changes to the given property and respond to modification events. This requires
     * a getter and setter method for the given property on the selected views. Passing "*" will
     * add the property observer for all of the fields in each selected view. For example:
     * <pre>
     * $.with(myButton).observe("selected", new Function() {
     *     @Override
     *     public void invoke($ droidQuery, Object... params) {
     *         Observation ob = (Observation) params[0];
     *         Log.i("$", ob.property + " changed to " + ob.newValue);
     *     }
     * });
     * </pre>
     * @param property name of the property to observe. If set to "*", all fields will be observed.
     * @param onPropertyChanged the Function to call when the given property has changed. The argument
     * passed to {@code onPropertyChanged} will be an instance of {@link ViewObserver.Observation},
     * and will contain the old value, new value, and the property name. The given instance of droidQuery
     * will have the observing view selected.
     */
    public $ observe(String property, Function onPropertyChanged)
    {
        for (View view : views)
        {
            Map<String, WeakReference<Observer>> kvo = observers.get(view);
            if (kvo == null)
            {
                kvo = new HashMap<String, WeakReference<Observer>>();
            }

            WeakReference<Observer> ref = kvo.get(property);
            if (ref != null && ref.get() != null)
            {
                if (property.equals("*"))
                    ref.get().support.removePropertyChangeListener(ref.get().kvo);
                else
                    ref.get().support.removePropertyChangeListener(property, ref.get().kvo);
            }
            Observer observer = new Observer();
            observer.support = new PropertyChangeSupport(view);
            observer.kvo = new ViewObserver(onPropertyChanged);
            ref = new WeakReference<Observer>(observer);
            if (property.equals("*"))
                observer.support.addPropertyChangeListener(observer.kvo);
            else
                observer.support.addPropertyChangeListener(property, observer.kvo);

            kvo.put(property, ref);
            observers.put(view, kvo);

        }
        return this;
    }

/**
 * Contains Objects pertaining to the property change listener for a view in droidQuery.
 */
public static class Observer
{
    /** Manages property observers registered to receive events */
    public PropertyChangeSupport support;
    /** The property observer */
    public ViewObserver kvo;
}
0

There are 0 answers