Pregunta

Intentaré explicar mi problema lo más claro posible :). Estoy usando PropertyChangeSupport para notificar las vistas registradas de los cambios en las propiedades. Una de las propiedades es un objeto cuyas propiedades se cambian cada segundo de vista. No quiero crear una nueva instancia para este objeto en particular cada vez que se actualice (para que propertychangelistener note el cambio), por lo que escribí mi propio método de iguales donde omito la comparación a sí mismo.

@Override
public boolean equals(Object item) {
    // do not compare 
    // if (this == item) { return true; }

    if (!(item instanceof TransferQueueItem) || 
        item == null) {

        return false;
    }

    TransferQueueItem newItem = (TransferQueueItem) item;
    boolean value = 
            // ommited... properties comparation
    return value;
}

Desafortunadamente eso no tiene el efecto que estaba buscando. Si creo una copia del objeto y le disparo el método de cambio de propiedad, funciona bien.

¿Qué me estoy perdiendo aquí?

- Editar

Me di cuenta de que, dado que estoy usando la misma instancia y no una copia de ella, las propiedades apuntan al mismo lugar, por lo que la comparación siempre resultaría cierta. ¿Hay una solución a eso (además de crear una copia). O qué tan malo es crear una copia de un objeto cada segundo, por ejemplo,

¿Fue útil?

Solución

Siempre debe devolver true para indicar a PropertyChangeSupport que su objeto no cambió. Pero eso significa que equals () está roto para todos los objetos de esta clase (por lo que ya no puede usarlos en conjuntos o mapas, por ejemplo).

Una mejor manera sería tener un método especial firePropertyChange () para este tipo de objeto que realiza el manejo especial. De esta manera, incluso puede evitar crear una instancia de PropertyChangeEvent , también. Aquí hay un ejemplo para manejar BigDecimal (donde equals () no funciona en absoluto):

protected transient PropertyChangeSupport changeSupport = null;

public void addPropertyChangeListener (String propertyName, PropertyChangeListener listener)
{
    if (changeSupport == null)
        changeSupport = new PropertyChangeSupport (this);

    changeSupport.addPropertyChangeListener (propertyName, listener);
}

public void firePropertyChange (String propertyName, BigDecimal oldValue, BigDecimal newValue)
{
    if (changeSupport == null)
        return;

    if (oldValue != null && newValue != null && oldValue.compareTo (newValue) == 0) {
        return;
    }
    changeSupport.firePropertyChange(new PropertyChangeEvent(this, propertyName,
                                               oldValue, newValue));
}

[EDITAR] Lo que haces es algo completamente distinto: tienes un padre y un hijo y quieres que los oyentes del padre reciban eventos cuando el hijo cambia.

El enfoque correcto aquí es agregar PropertyChangeSupport al child . Cuando el niño se agrega al padre, el padre debe instalar los oyentes necesarios en el niño. Cuando se activa un evento, debe disparar un segundo evento que informe a los oyentes del padre del cambio en el hijo (el padre debe enviar los eventos).

Otros consejos

este es un caso de activistas de propiedades encadenados:

TransferQueueItem debe lanzar sus propios PropertychangeEvents que deben ser escuchados por TransferQueue en el que se inserta

Y, en respuesta, TransferQueue debe notificar a sus oyentes que un artículo de su propiedad ha cambiado.

Cada vez que tengo un problema como este en el que un objeto debe relanzar eventos, uso esta convención (de mi equipo de trabajo):

1 Un objeto solo puede iniciar eventos cuya fuente es ella misma.

2 Si desea un evento delegado, lanza un evento como este: nuevo PropertyChangeEvent (este, " DELEGATED_EVENT " ;, null, receiveEvent). Para que los oyentes puedan seguir la cadena de eventos.

Además, tengo un método estático en una clase de Util que sigue la cadena de eventos y devuelve el primer evento, la única propiedad de whick no es " DELEGATED_EVENT "

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top