Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

361
Views
ListAdapter DiffUtils newItem y oldItem son iguales cuando se llama a submitList()

Solo para su información, no estoy buscando exactamente una "solución", sino una explicación y una discusión que pueda ayudar a comprender un poco más cómo funcionan cosas aparentemente tontas como estas.

Estaba trabajando en este proyecto más grande cuando me di cuenta de que, en algún lugar, cierta lista no se actualizaba correctamente. Mirando un poco más de cerca, los elementos se estaban modificando correctamente, y si "se desplazaba hacia afuera" y hacia atrás, la información del elemento se mostraría correctamente.

Me topé con este artículo: ListAdapter no actualiza el elemento en RecyclerView

Pero la diferencia aquí es que, de hecho, se estaba llamando a DiffUtils, ¡pero de alguna manera newItem y oldItem eran iguales! Entiendo que la biblioteca asume que está usando Room o cualquier otro ORM que ofrece una nueva lista asíncrona cada vez que se actualiza , pero aquí está la cuestión. Si envío la lista "ingenuamente", DiffUtils ni siquiera se llama. Pero, si envío la lista como list.toMutableList() como sugieren algunos entonces, se llama a DiffUtils, pero de alguna manera los elementos, nuevos y antiguos, ya son los mismos, por lo tanto, nada se actualiza en ese momento (verificado esto colocando puntos de interrupción dentro areContentsTheSame ).

Te dejo aquí los fragmentos relevantes y un enlace a un proyecto de prueba que creé solo para poder encapsular el comportamiento y probarlo por separado de todo lo demás.

El Fragmento - simplemente llamando a la lista de envío

 viewModel.items.observe(viewLifecycleOwner) { adapter.submitList(it.toMutableList()) }

Ver modelo

 private val _items = MutableLiveData<List<SimpleItem>>() val items: LiveData<List<SimpleItem>> get() = _items init { _items.value = ItemsRepo.getItems() } fun onItemClick(itemId: Int) { ItemsRepo.addItemCount(itemId) _items.value = ItemsRepo.getItems() }

El "Repo" creo algunos objetos de datos ItemsRepo {

 private var items = mutableListOf( SimpleItem(1), SimpleItem(2), SimpleItem(3), SimpleItem(4), SimpleItem(5) ) fun getItems(): List<SimpleItem> { return items } fun addItemCount(itemId: Int) { items.find { it.itemId == itemId }?.let { it.itemClickCount += 1 } }

El repositorio de GitHub: https://github.com/ellasaro/ListAdapterTest

¡Salud!

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

No use clases de datos mutables o listas mutables con DiffUtil. Puede dar lugar a todo tipo de problemas. DiffUtil se basa en la comparación de dos listas, por lo que si una de ellas es mutable y se ha modificado, no puede comparar la antigua y la nueva con éxito porque no hay registro del estado anterior.

No me tomé el tiempo para reducir su problema exacto, pero apuesto a que si cambia getItems() de su Repo para devolver items.toList() (por lo que mutar el Repo no muta las listas descendentes), y cambia SimpleItem para que sea una clase inmutable, tus problemas desaparecerán.

Desafortunadamente, hacer que SimpleItem sea inmutable será un poco complicado. El oyente de clics en lugar de mutar el elemento tendrá que informar al repositorio la identificación del elemento que cambió, y el repositorio debe cambiarlo manualmente y luego actualizar la lista.

Será más limpio si su Repo devuelve un Flujo de listas que se emite automáticamente cuando se le informan cambios. Entonces, su ViewModel no tiene que informar los cambios y luego recordar consultar manualmente el estado de la lista nuevamente.

toList() y no toMutableList() . Una lista mutable comunica que planea mutar la lista en lugar de simplemente leerla, lo que nunca debe hacer con una lista que se pasa a un DiffUtil.

over 4 years ago · Santiago Trujillo Report

0

Declarar la propiedad itemClickCount como val y obtener la lista como una lista inmutable del objeto Repo hizo el truco como sugirió Tenfour04 .

Como observación adicional, si mantiene la propiedad itemClickCount como var pero reemplaza el elemento por completo y vuelve a enviar la lista actualizada, funciona correctamente. Entonces, el problema parece estar modificando la propiedad mutable del objeto directamente en la lista de Repo . Usar .toList() en getList() no ayudó en ese caso.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!