I've got a question about the performance of a ListView. My application uses a ListView with approximately 20 items and i was wondering what should i do if the data of one item has changed. Should i call notifyDataSetChanged() on the adapter and cause a redraw of the whole list or should i take care only of the item to refresh itself?
What is the cost of notifyDataSetChanged()? Can i use this without hesitation? An ListView item of mine has about 3-4 TextViews and an ImageView.
Any suggestions?
notifyDatasetChanged refreshes the whole list each time its called so it is better if you call that after you have all of your data that you want so you are not doing unnecessary work
mMyListView.invalidate();
mMyListView.invalidateViews();
Related
I need the functionality to update the data in the item in the recycler view. right now, If we notify the whole item it shows some fluctuation and we want to avoid refreshing the whole item on the UI.
I am using the ListAdapter with diff utils.
There are many ways to achieve your goal.
self-managing items. Adapter doesn't know anything about content of the items, it only puts items into RecyclerView. Content is managed by the item itself, so your problem is already solved.
custom adapter. Adapter has intricate knowledge about every item and can update selected ones accordingly.
AsyncListDiffer You can add differ to your adapter and it will take care of not updating parts that need no update.
Without seeing your code, we can't tell which way would be the most appropriate for you, but I guess adding differ is the simplest on already working code.
You need to create custom Adapter:
https://developer.android.com/develop/ui/views/layout/recyclerview
If you're talking about updating specific list items, and you're not using a DiffUtil (which will handle it for you) then you need to call the appropriate notify* method on your Adapter.
They fall into two categories, item change events (where the item list stays the same, but the displayed data for one or more of those items changes) and structural change events (where the actual list of items changes in some way, e.g. insertion/removal, or reordering).
I'm assuming you just want to update the displayed data for an item, so you should use one of the notifyItemChanged or notifyItemRangeChanged methods to inform the adapter that a certain item (or range of items) needs to update. If any of those items are currently being displayed in a ViewHolder, then onBindViewHolder will get called again for those items - which is where you set all your text, images etc depending on the item you're displaying. So you'll update them with the current data.
Both those methods have a version that takes a payload Object/Any, where you can pass in some data to be used in a partial bind - basically, onBindViewHolder can receive that data and be smarter about the update, which means you can avoid things like reloading images, etc. by passing in some stuff and checking for it during the binding process. More info about that here in the other version of onBindViewHolder you can implement, if you need to.
I know that notifydatasetchanged updates the whole list and it is recommended to use DiffUtil to only update changed items, what I am not understanding yet after a lot of research is if it's expected that notifydatasetchanged animates list items separately when being used in a RecyclerView. Because I have one RecyclerAdapter where I replace the dataset completely and then call notifyDataSetChanged leading to list items being animated perfectly, only those added get the default added animation, removed ones get the removed animation and so on. At the same time I have another adapter where I also do the same, call notifyDataSetChanged but here the whole list flashes shortly, I am not getting any animations automatically, so I don't know from what does notifydatasetchanged make this dependent? Both adapters are too complex and long to post here.
I found the answer here:
The framework will attempt to animate views if your adapter uses
stable IDs, which provides enough data to guess which views are
removed/added/etc
I'm using recycler view with grid view (every item contains a grid) with thumbnail images after adding images in view it start uploading, and i need to change some values (status) in model at the time of start and finish upload.
What I'm currently doing is change values in model and call notifyDataSetChanged, but it causes to slow down application (hang some times) because it updating every child of list :(
Can any one help me with this?
Call notifydatasetchanged() for particular Gridview adapter only. Don't call notifydatasetchanged() for complete recyclerview adapter.
Try setting it again to the adapter.
gridview.setAdapter(your adapter)
-passing your new list to your adapter.
I believe notifyDataSetChanged updates all of your values regardless if they have a change or not that is why it is slow. I suggest you try using notifyItemChanged(int position) instead.
According to recyclerview docs this is what notifyDataSetChanged does:
This event does not specify what about the data set has changed, forcing any observers to assume that all existing items and structure may no longer be valid. LayoutManagers will be forced to fully rebind and relayout all visible views.
Old question but similar to what I'm experiencing.
RecyclerView is usually incredibly fast when changing list details. But manipulating a lot of images can really slow it down if you're not careul.
I'd recommend you try removing the images and repeat it so you can see if that is just as slow. I suspect this will be a lot faster.
If so, make sure you're handling the images off the UI thread. The Android docs recommend you use a library such as Glide which also handles sub-sampling the image to make sure it's the right size.
Hope that helps!
every time when I call notifyDataSetChanged() on my adapter the listview displayes the last item in the adapter array.
Is there any possible way to scroll the listview to the top off screen, since the setSelection(n) method within the post runnable is noticable, because the listview jumps to the bottom and then to the top. This movement can be seen on the screen unfortunately.
Thanks in advance.
When you call notifyDataSetChanged(), you're telling the ListView to refresh its contents, and it will actually try not to scroll if possible. It knows what it's currently scrolled to based on the items' positions and ids that it has obtained from the adapter. Your issue may be that your adapter is giving out inconsistent ids from getItemId that are confusing the ListView, causing it to scroll unnecessarily. Can you explain a little more about what your code is doing at the time you call notifyDataSetChanged()? Are you adding or removing items in the adapter at the same time?
I think this is what you need:
lv.setSelection(0);
Is there any difference between ListView.invalidateViews() and Adapter.notifyDataSetChanged()?
Well yes, there is.
ListView.invalidateViews() is used to tell the ListView to invalidate all its child item views (redraw them).
Note that there not need to be an equal number of views than items. That's because a ListView recycles its item views and moves them around the screen in a smart way while you scroll.
Adapter.notifyDataSetChanged() on the other hand, is to tell the observer of the adapter that the contents of what is being adapted have changed. Notifying the dataset changed will cause the listview to invoke your adapters methods again to adjust scrollbars, regenerate item views, etc...
Most of the time you would want to use notifyDataSetChanged instead of invalidateViews, but it certainly depends on what you are trying to accomplish.