Reputation: 370
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.
Upvotes: 0
Views: 416
Reputation: 501
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)
Upvotes: 0