Search code examples
kotlinandroid-roomshared-memoryandroid-livedataandroid-diffutils

Object with same memory reference LiveData with Room DB and DiffUtil


I am trying to integrate the list with Room DB and Diff Utils,

Flow Diagram

Issue Facing:

  • When an item(s) is updated, LiveData got triggered but existing items in the adapter are the same as newItems. eg. OldList = [0 : "zero", 1: "one"] NewList = [0: "0", 1:"1"] when update triggered Adapter.currentList = [0:"0", 1:"1"] issue happening without setting items to adapter list
  • Old List same as NewList without set

Code:

Room - Listening Changes :

@Query("SELECT * FROM tbl_topic_list ORDER BY created_at DESC")
abstract fun getTopicListLiveData():LiveData<List<FilteringTopicEntity>>

LiveData - Listening Changes:

viewModel.getTopicListLiveData().observe(this, { list: List<FilteringTopicEntity> ->
            itemAdapter?.let {
                it.setData(list.toMutableList())
            }.orElse {
                itemAdapter = TopicListingAdapter(list
                    .toMutableList(), itemListener)
                itemTopicRecyclerView.adapter = itemAdapter
            }
            Log.e(TAG, "Item Received ${list.size}")
        })

Inserting into DB

@Update(onConflict = OnConflictStrategy.REPLACE)
abstract fun updateFilterTopic(copyDataEntity: FilteringTopicEntity)

Updating DB Row value

    override fun updateTopic(topicEntity: FilteringTopicEntity) {
        topicEntity.updatedAt = DateTime()
        topicListDao.updateFilterTopic(topicEntity)
    }
class MediaDiffCallback(
        private val oldList: MutableList<FilteringTopicEntity>,
        private val newList: MutableList<FilteringTopicEntity>
    ) : DiffUtil.Callback() {

        override fun getOldListSize(): Int = oldList.size

        override fun getNewListSize(): Int = newList.size

        override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
            return oldList[oldItemPosition].id == newList[newItemPosition].id
        }

        override fun areContentsTheSame(oldPosition: Int, newPosition: Int): Boolean {
            return oldList[oldPosition].updatedAt ==  newList[newPosition].updatedAt
        }

        @Nullable
        override fun getChangePayload(oldPosition: Int, newPosition: Int): Any? {
            return super.getChangePayload(oldPosition, newPosition)
        }
    }

Adapter complete code : link

I tried several solutions nothing works for that issue

  • I tried toMutableList() & toList()
  • I tried data class and converting it into objectList.map {it.copy}.toList()
  • Extracting values and adding to another object instance and new list
  • Tried to update latest livedata, room dependencies

LiveData received items present already in the adapter without set

Please help to find out notifying list item changes without notifyDataSetChanged() method to integrate things properly with DiffUtils.


Solution

  • Problem Solved

    Initially, list items loaded within the adapter and selected item changed and replaced to DB.

        @Update(onConflict = OnConflictStrategy.REPLACE)
        abstract fun updateFilterTopic(copyDataEntity: FilteringTopicEntity)
    

    Here, the problem is I used the same item instance which room DB returned before.

    So. I reassigned values to the new instance and updated it to DB, now updates receiving as expected.

    open class FilteringTopicEntity() : com.support.room.BaseEntity(), Parcelable {
        fun copy(filteringTopicEntity: FilteringTopicEntity): FilteringTopicEntity {
            filteringTopicEntity.id = id
            filteringTopicEntity.updatedAt = updatedAt
            filteringTopicEntity.createdAt = createdAt
            return filteringTopicEntity
        }
    }
    

    Here I showed, how I copied a value

        filteringTopicEntity.copy(FilteringTopicEntity()