es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Implementando la equivalencia de objetos Room sin clave principal agnóstica.

Considere la siguiente simple data class que se utiliza como una Room @Entity

@Entity
data class SimpleDataClass(
    val name: String,
    val timestamp: String,
    val isInvalid: Boolean = false,
    @PrimaryKey(autoGenerate = true) val id: Int = 0
)

La funcionalidad que estoy tratando de implementar es que dos objetos de tipo SimpleDataClass deben considerarse iguales si todas sus propiedades son iguales, sin importar su id (que solo se agrega a la estructura de la clase porque se almacenará en una base de datos). Por ejemplo, el timestamp solo almacena el día del mes y el usuario hizo lo mismo durante muchos meses.

Tenga en cuenta que, como registros de base de datos, deben considerarse por separado, ya que el usuario realmente generó dos registros y, por lo tanto, tienen claves primarias incrementadas automáticamente diferentes.

Esto se puede lograr escribiendo un método equals explícito que ignore la comparación de id. Sin embargo, también sería necesario escribir otros métodos de comparación como hashCode y toString, los cuales trato de evitar (permitiendo que el compilador los genere).

Para permitir que el compilador ignore id, seguí el consejo aquí.

@Entity
data class SimpleDataClass(
    val name: String,
    val timestamp: String,
    val isInvalid: Boolean = false,
) {
    @PrimaryKey(autoGenerate = true)
    var id: Int = 0
}

Tenga en cuenta que id ahora es una variable var para permitir su modificación.

Esto logra lo que buscaba, excepto que rompe la función de copiado. Cuando se copia un registro leído de la base de datos como un objeto SimpleDataClass (a través de simpleDataClass.copy()), su id no se transfiere a la copia. Para remediar esto, estoy usando:

old.copy(/*cambiar algunos parámetros, o no*/).also { it.id = old.id }

Ninguno de los métodos parece ser satisfactorio. ¿Cómo se puede lograr esto?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para lograr la funcionalidad de considerar dos objetos SimpleDataClass iguales si todas sus propiedades son iguales sin importar el campo id, puedes modificar la clase SimpleDataClass de la siguiente manera:

    @Entity
    data class SimpleDataClass(
        val name: String,
        val timestamp: String,
        val isInvalid: Boolean = false,
        @PrimaryKey(autoGenerate = true) val id:Int=0
    ) {
        override fun equals(other: Any?): Boolean {
            if (this === other) return true
            if (javaClass != other?.javaClass) return false
    
            other as SimpleDataClass
    
            if (name != other.name) return false
            if (timestamp != other.timestamp) return false
            if (isInvalid != other.isInvalid) return false
    
            return true
        }
    
        override fun hashCode(): Int {
            var result = name.hashCode()
            result = 31 * result + timestamp.hashCode()
            result = 31 * result + isInvalid.hashCode()
            return result
        }
    }
    

    Esta implementación sobrescribe las funciones equals y hashCode de la clase SimpleDataClass para comparar únicamente las propiedades name, timestamp y isInvalid, y no la propiedad id. De esta manera, dos objetos SimpleDataClass que tengan los mismos valores para name, timestamp e isInvalid se considerarán iguales. Ten en cuenta que la propiedad id se deja tal cual, ya que Room requiere que el campo @PrimaryKey esté presente.

    Con esta implementación, no será necesario modificar el campo id por separado al copiar los objetos SimpleDataClass. Sin embargo, al consultar la base de datos de Room, deberás utilizar el método distinctUntilChanged() para filtrar los objetos iguales y evitar duplicados, ya que aún tienen diferentes valores de id en la base de datos.

Comments are closed.