DiffUtil.Callback() not working as the same as notifyDataSetChanged() - android

I have a message list that contains messages. And I used a regular RecyclerView.Adapter instead of ListAdapter.
ChatFragment
chatViewModel.msgListDisplayLiveData.observe(viewLifecycleOwner, {
chatAdapter.setChat(it)
})
Here is the function to update messageList in adapter.
ChatAdapter
fun setChat(newMessages: List<Message>) {
val diffUtil = ChatDiffUtil(messageList, newMessages)
val diffResults = DiffUtil.calculateDiff(diffUtil)
messageList = newMessages
diffResults.dispatchUpdatesTo(this)
--> Method of using notifyDataSetChanged()
// messageList = newMessages
// notifyDataSetChanged()
}
Previously I am using notifyDataSetChanged() and the list item can be updated instantly, but without any animation.
Thus, I decided to use DiffUtils() and I got the nice animation when my list's item got append/remove.
However, when I want to update one of the item, DiffUtils seems do not have any visible effect.
Using notifyDataSetChanged() - can instantly update the row.
Using DiffUtils() - cannot update instantly.
What had I done wrongly? Please advise me.

Related

NotifyDataSet Changed Android - Recycler View Adapter

val recyclerView = findViewById<RecyclerView>(R.id.rv)
val adapter = UserDetailsAdapter(users)
recyclerView.adapter =adapter
recyclerView.layoutManager= LinearLayoutManager(this)
Thread{
userDao.insertAll(user,user2,user3)
users= userDao.getAll() as ArrayList
Log.d("Checking Service",users.size.toString())
recyclerView.post {
Log.d("Checking Service","Data set Changed")
adapter.notifyDataSetChanged()
}
}.start()
Here recycler view in the UI does not updating the items .
runOnUIThread also tried but not working.
kindly explain why notify data set changed not working. and tell me how to update recycler view adapter from another thread.
You need to update the users data inside the adapter before actually calling notifyDataSetChanged().
In your case you need to update the data source which you initialised in adapter constructor .
add this function to your adapter instead of calling notify adapter change from activity
fun updateAdapter(users: ArrayList<User>) {
this.users= users
notifyDataSetChanged()
}
and call this function
adapter.updateAdapter(users)

How to stay at the same position in the RecyclerView even after fetching the updated data from the Firestore

I have a list of items in a RecyclerView that fetched from the Firestore database. Whenever I add, delete or edit an item I call respective function to make changes in the Firestore and then I call the getProductListFromFireStore() to update the RecyclerView. But the problem that I have is every time I make these changes, I go to the top of the list. I want to stay where I was even after adding/deleting or editing. How can I do that?
I didn't have the notifyDataSetChanged() in my code earlier, this was added to check if this will do the job, I do not know if I have done this right.
The following function is called when the product list is successfully fetched from the Firestore
fun successProductsListFromFireStore(productsList: ArrayList<Product>) {
hideProgressDialog()
if (productsList.size > 0) {
binding.rvMyProductItems.layoutManager = LinearLayoutManager(activity)
binding.rvMyProductItems.setHasFixedSize(true)
val adapterProducts =
MyProductsListAdapter(requireActivity(), productsList, this#ProductsFragment)
binding.rvMyProductItems.adapter = adapterProducts
adapterProducts.notifyDataSetChanged()
} else {
binding.rvMyProductItems.visibility = View.GONE
binding.tvNoProductsFound.visibility = View.VISIBLE
}
}
I think u need to use DiffUtill. It automatically update only changed items and if at least one item on screen was not changed then u will stay on the same position

How to update RecyclerView using Kotlin and Room?

I am trying to display data from my Room database on RecyclerView, it works fine except when I fill in new data and try to update my RecyclerView it doesn't update. Here's part of the code that I tried using:
MainActivity.kt
val adapter = MainAdapter(myData)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = adapter
MainAdapter.kt
fun refresh(data: List<NewList>) {
val currentList: MutableList<MyList> = mutableListOf()
currentList.clear()
currentList.addAll(data)
notifyDataSetChanged()
}
I am trying to call this function from Fragment file so it can pass updated list from Room Database (It updates list once someone opens that fragment)
Fragment.kt
var myData = App.instance.db.getAllDao().getAll()
val adapter = MainAdapter(myData)
adapter.refresh(myData)
I printed updated list in the updateData() function and it does show updated list, as well as tried printing ItemCount and it also shows updated ItemCount, but does not update actual display with new data.
The adapter attached to the RecyclerView in MainActivity and in fragment are not same.
just delete adapter creation in Fragment and pass RecyclerView instance to Fragment and then set layout manager and adapter there instead of activity. lastly call updateData method in order to be able to populate adapter.

RecyclerView DiffUtil need to update the data manually?

now I find a bug in my project
val diffCallback = diff.newInstance(list, newList)
val diffResult = DiffUtil.calculateDiff(diffCallback)
list.clear()
list.addAll(newList)
diffResult.dispatchUpdatesTo(this)
this is my diff code in my adapter, you can see I clear old list and update the new list.
but I use data in viewholder and set tag with it in a view.
when I set old data as a tag in a view, then I diff the list, because as this diffUtil return true, so view also handler old data in his tag, but I always update adapter list when diff, so when I use adapter.list.getindex(data) I get -1 because view tag is old data, and my adapter list had to update new list, Even if the old list data view == new list.
when I remove list.clear() list.addAll(newList), the diff cannot succeed,
someone can tell me why? and how can I solve this problem?

Should notify data-set-change out side of adapter?

I'm doing notifying data-set-change inside of Adapter.
like,
fun setItems(items: MutableList<IMyModel>) {
list = items
notifyDataSetChanged()
}
fun updateItems(pos: Int: item: IMyModel) {
list[pos] = item
notifyItemChanged(pos)
}
But in many tutorials, I can see they do outside of the Adapter.
adapter.setItems(items)
adapter.notifyDataSetChanged()
So I just wondered if there is any reason I should notify that outside of Adapter? like a bad practice?
Usually, you should call notify directly after changing the dataset, no matter in which class that change occurs.

Categories

Resources