0

I have a recyclerview which displays multiple viewholders containing horizontal rows, grids, vertical lists etc so my Model that I pass to the recyclerview has a few different lists contained in it.

Some of the data in the List is genereated by dagger at compile time and other lists within that model are updated when the network requests from the api completes.

The problem is when I pass the updated List the UI never updates. I have to move into another screen then come back again to see the UI updated or just manually pass false in the diff util areContentsTheSame

Model

data class Model(
var id: String,
val viewType: String,
val title: Int?,
val textColour: Int,
val order: Int,
var header: HeaderModel?,
var videoList: List<VideoModel>? = emptyList(),
var quotesList: List<QuotesModel>? = emptyList(),
var tileList: List<TileModel>? = emptyList(),
var gratitudeList: List<String>? = emptyList(),
) {
override fun equals(other: Any?): Boolean {
    if (this === other) return true
    if (javaClass != other?.javaClass) return false

    other as Model

    if (id != other.id) return false
    if (viewType != other.viewType) return false
    if (title != other.title) return false
    if (textColour != other.textColour) return false
    if (order != other.order) return false
    if (header != other.header) return false
    if (videoList != other.videoList) return false
    if (quotesList != other.quotesList) return false
    if (tileList != other.tileList) return false
    if (gratitudeList != other.gratitudeList) return false

    return true
}

Adapter Diff

 val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Model>() {
    override fun areItemsTheSame(
        oldItem: Model,
        newItem: Model
    ): Boolean {
        val value = oldItem.id == newItem.id
        return value
    }

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

private val differ = AsyncListDiffer(this, DIFF_CALLBACK)

fun submitList(list: List<Model>?) {
    differ.submitList(list)
    //  notifyDataSetChanged()
}

Fragment

homeViewModel.viewState.observe(viewLifecycleOwner, { viewState ->
        if (viewState != null) {
            viewState.modelList?.let { list ->
                homeAdapter?.submitList(list)
            }
        }
    })

Update to the videoList

 fun updateListVideos(list:  List<VideoModel>?) {
    val update = getCurrentViewStateOrNew()
    setViewState(update.apply{ modelList?.get(1)?.videoList = list)
}

I've read so many other questions on this that suggest in the live data observer pass list.toMutableList to essentially create a new list - Tried it doesnt work. The only hack that worked was calling submitList(null) before submitting the list which causes the whole UI to "flash". Other than that Ive had to revert back to NotifyDataSetChange which obviously defeats the whole purpose of having a diff util. Any help solving this would be great.

12
  • you should call notifyDataSetChanged() after data has been added/updated Commented Dec 29, 2021 at 18:16
  • Then whats the point of diff util? Commented Dec 29, 2021 at 18:23
  • What's the difference between Model and SectionModel? It's really weird that you're overriding equals for a data class, but also in your implementation you are assuming the other object being compared to Model is a SectionModel, which is not guaranteed. Also, a tip: Avoid nullable List properties, since it's easier to work with non-null Lists and just use emptyList() to represent them when they contain nothing. Commented Dec 29, 2021 at 18:46
  • The sectionModel was a typo, I edited the question. The overriding changees nothing Ive also edited that back. Thanks for the tip on empty lists Commented Dec 29, 2021 at 19:06
  • Try with StateFlow and collectLatest. It doesn't update if dataset is the same and try debugging if it posted new value. Commented Dec 29, 2021 at 19:11

1 Answer 1

0

Your old and new lists have the same referenced fields. That's why, diff util is not recognizing the change. You should either update your equals override and compare each field of lists or when you want to update your oldList do it like below:

val newList = oldList.map { it.copy() }
homeAdapter?.submitList(newList)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.