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.
notifyDataSetChanged()after data has been added/updatedequalsfor adata 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 useemptyList()to represent them when they contain nothing.StateFlowandcollectLatest. It doesn't update if dataset is the same and try debugging if it posted new value.