Diff util not updating items in recycler

65 views Asked by At

I have problems updating data into recycler view. Im using adapter with diffutil

class DiffUtilCallback : DiffUtil.ItemCallback<SectorItemDataUI>() {
    override fun areItemsTheSame(oldItem: SectorItemDataUI, newItem: SectorItemDataUI): Boolean {
        return oldItem.sectorId == newItem.sectorId
    }

    override fun areContentsTheSame(oldItem: SectorItemDataUI, newItem: SectorItemDataUI): Boolean {
        return oldItem == newItem
    }

}

In the viewModel i have the liveData

private val _sectorItem: MutableLiveData<MutableList<SectorItemDataUI>> =
        MutableLiveData()
val sectorItem: LiveData<MutableList<SectorItemDataUI>> get() = _sectorItem

I have this method to update the values (only temperature or humidity)

private fun updateMeasurementItem(measurement: List<NetworkMeasurement>) {
        val lastMeasurement = measurement.lastOrNull() ?: return

        _sectorItem.value = _sectorItem.value.also {
            it?.find { item -> item.temperatureSensorId == lastMeasurement.sensorId }?.temperature =
                lastMeasurement.value.toString()
            it?.find { item -> item.humiditySensorId == lastMeasurement.sensorId }?.humidity =
                lastMeasurement.value.toString()
        }
    }

And in the fragment i update the list into te recycler

viewModel.sectorItem.observe(viewLifecycleOwner) {
      homeSectorAdapter.submitList(it)
}

But for some reason, the data in the recycler is not updating. If i put Log before homeSectorAdapter.submitList(it), the data is correctly displayed in the logcat

if i create new instances of the data, the recycler updates correctly the data. But i know taht this isnt a good practice, so i dont want to make this.

private fun setupObservers() {
        viewModel.sectorItem.observe(viewLifecycleOwner) { data ->
            val aux: MutableList<SectorItemDataUI> = mutableListOf()
            data.forEach {
                aux.add(
                    SectorItemDataUI(
                        it.sectorId,
                        it.sectorName,
                        it.temperature,
                        it.temperatureSensorId,
                        it.humidity,
                        it.humiditySensorId
                    )
                )
            }
            homeSectorAdapter.submitList(aux)
        }
    }
1

There are 1 answers

0
Guillaume Muret On

Your code seems to be good, maybe in the update method in your adapter.

Try with something like this :

fun updateList(
    newItems: List<SectorItemDataUI>,
    readOnly: Boolean = false,
) {
    val diffResult = DiffUtil.calculateDiff(object : DiffUtil.Callback() {
        override fun getOldListSize(): Int {
            return [email protected]
        }

        override fun getNewListSize(): Int {
            return newItems.size
        }

        override fun areItemsTheSame(
            oldItemPosition: Int,
            newItemPosition: Int,
        ): Boolean {
            return ([email protected][oldItemPosition]::class == newItems[newItemPosition]::class) && ([email protected][oldItemPosition].sectorId == newItems[newItemPosition].sectorId)
        }

        override fun areContentsTheSame(
            oldItemPosition: Int,
            newItemPosition: Int,
        ): Boolean {
            return [email protected][oldItemPosition]::class == newItems[newItemPosition]::class && [email protected][oldItemPosition] == newItems[newItemPosition]
        }
    })
    with([email protected]) {
        clear()
        addAll(newItems)
    }
    diffResult.dispatchUpdatesTo(this)
}

The clear and addAll is used to update the model completely and the diffUtil is used to tell the adapter which items must be updated in the view (only content or ViewHolder completely).