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

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.

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)

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

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.

KOTLIN I can't delete data from sqlite database kotlin RecyclerView

I've a recyclerview and I want to delete a recyclerview item.
fun deleteItem(position: Int){
ModelList.removeAt(position)
notifyItemRemoved(position)
notifyDataSetChanged()
}
override fun onBindViewHolder(holder: myRecyclerViewAdapter.ViewHolder, position: Int) {
holder.bind(ModelList[position])
holder.itemView.listRowDelete.setOnClickListener {
deleteItem(position)
}
I deleted items with this method but because of these items are in sqlite database they all come back when I restard the app. I can't reach positions from my mainactivity and I cant reach database inside of adapter. How can I delete specific item from sqlite database which I want to. Please help thank you
For onClickListener , Don't rely on position from the onBindViewHolder
Instead get the position from holder like this
holder.itemView.listRowDelete.setOnClickListener {
deleteItem(holder.adapterPosition)
}
InClickListeners and things that happen afterwards , get the accurate position with adapterPosition , hover over the adapter position to see the quick documentation !
If you want to call database method , I would suggest you to not call it in Adapter & rather have methods to set custom listeners to adapters which can be called with the victim (item supposed to be deleted)
have a function like this in your adapter
Define the listener property like this
private val myListener:MyCustomListenerInterface = MyCustomListenerInterface{}
Have a setter function to set listener
fun setListener(l:MyCustomListenerInterface){
myListener = l
}
interface MyCustomListenerInterface{
fun onDelete(model)
}
Then in your onClickListener call the onDelete of the custom listener interface like this
holder.itemView.listRowDelete.setOnClickListener {
myListener.onDelete(modelItem)
}
Now When Initializing the adapter for recycler view in fragment/activity , set the listener !!

RecyclerView's row item views hide/show getting messed up on scroll of the Recyclerview

I am using a RecyclerView to show list of products in my app, I need to group the product based on aisle. while the data are fetched for the first time in the list, the products are grouped correctly with respect to aisle. When we scroll the view, the aisle group divider is shown for the wrong item and the divider gets restored to correct position once the onBindViewHolder gets refreshed automatically.
MyAdapter.class
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
itemsGrouping(pickItem, pickItemView, holder.adapterPosition)
}
private fun itemsGrouping(pickItem: PickItem, pickItemView: View, adapterPosition: Int) {
//Based on some condition
if(SomeCondition)
itemDivider(pickItemView,true)
else
itemDivider(pickItemView,false)
}
private fun itemDivider(v: View, boolean: Boolean) {
if(boolean) {
v.visibility = View.VISIBLE
} else {
v.visibility = View.GONE
}
}
Well, you should know that the view holders are reused in the RecyclerView, so it's probable not the right idea to try to determine the visibility of the divider in onBindViewHolder. I would recommend using item decorator for dividers. Here's the question and answer for that
How to add dividers and spaces between items in RecyclerView?
The problem is RecyclerView recycles previous views in order to be efficient.
I guess "SomeCondition" contains artifacts which are from previous holders.
So at
itemsGrouping(pickItem, pickItemView, holder.adapterPosition)
you should get pickItem and pickItemView from newly bound holder. You should use like
pickItemView = holder.findViewById(R.id.pickItemView);
Or consider using DataBinding Library
Here is a good example (it's in Kotlin) : DataBoundListAdapter
Once you extend your adapter to DataBoundListAdapter and override bind() method, everything inside bind is executed for every row, so you won't get repeated results.
Note : notice "executePendingBindings()"

How to find out item is created in recycler view for the first time?

I have a recycler view and I want to find out if an item is created in recycler view for the first time or not?
Is there an event handler for it?
Note: I know how to implement it with flag, but I'm looking for another approach.
Why do you want this? To my mind it seems like there is not a good reason to know this information, a ViewHolder should be independent from that knowledge.
Nothing is provided for this by RecyclerView.Adapter , the only callbacks are to manage the ViewHolder instances, which can be recycled and so any particular instance wouldn't know if it is the first instance or not.
You could store a flag in your data model and access it when you set up the ViewHolder in onBindViewHolder, as you seem to know.
You can ovveride onViewAttachedToWindow(holder: ViewHolder) in your recycler adapter. sample code like this:
private var isFirstChildAttached = false // single fire
override fun onViewAttachedToWindow(holder: ViewHolder) {
super.onViewAttachedToWindow(holder)
holder.pageView.registerTopLevelTouchListener()
if (!isFirstChildAttached) {
isFirstChildAttached = true
checkAndFirePageDimen(holder.itemView)
}
}
private fun checkAndFirePageDimen(itemView: View){
itemView.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
itemView.viewTreeObserver.removeOnGlobalLayoutListener(this)
pagerCallback.onFirstItemAttachedToPager(itemView)
}
})
}
"checkAndFirePageDimen" helps you for reliable itemView size.

Categories

Resources