Android. How does notifyDataSetChanged() method and ListViews work?
I've figured it out. I couldn't understand how the hell the adapter started and how did it know where to get the data from. When i extended the BaseAdapter
class, in the constructor of that class I initialized the list of items that I wanted to see in the ListView
. But I couldn't figure out how these values would be used and when.
So here's the thing !!! :
In the BaseAdapter
there are some methods that need to be overridden. Among these, there is getCount()
.
When the ListView
is created and whatnot, it calls getCount()
. If this returns a value different than 0 (I returned the size of the ArrayList which I've previously initialized in the constructor), then it calls getView()
enough times to fill the screen with items. For instance, I initialized the ArrayList
with 20 items. Because only 8 items initially fit on the screen, getView()
was called 8 times, each time asking for the position it required for me to return (more precisely it wanted to know how the row would look like in the list on that specific position, what data it needed to contain). If I scroll down the list, getView()
gets called over and over again, 'til I hit the end of the list, in my case 20 items / rows.
What notifyDataSetChanged()
does is ... when called, it looks at what items are displayed on the screen at the moment of its call (more precisely which row indexes ) and calls getView()
with those positions.
i.e. if you're displaying the first 8 items in the list (so those are the ones visible on the screen) and you add another item between the 2nd and 3rd item in the list and you call notifyDataSetChanged()
then getView()
is called 8 times, with positions starting from 0 and ending with 7, and because in the getView()
method you're getting data from the ArrayList
then it will automatically return the new item inserted in the list alongside 7 out of the previous 8 (7 and not 8 because the last item went one position down, so it is not visible anymore), and the ListView
will redraw, or whatever, with these items.
Also, important to specify is that if you've implemented getView()
correctly, you'll end up recycling the items (the objects) already displayed (instead of creating new ones). See this video at around 12:00 minutes to see the correct way to implement getView()
I've figured all this out by placing calls to LogCat
in every method and following what was going on.
Hope this helps someone who's just now starting to understand how ListView
s work.
P.S. This example also helped me a lot to understand.
UPDATE
Nowadays ListViews
are not really used anymore. Android came out with the RecyclerView
which does the recycling of the views for you, but knowing the basics of a ListView
helps with understanding the RecyclerView
.
Here's a link for reference: https://developer.android.com/guide/topics/ui/layout/recyclerview
How android's BaseAdapter notifyDataSetChanged method work?
Supposed I changed the 3rd element in my string array (array data for
the listview), what "any View reflecting the data set should refresh
itself" means ?
It means that any view which shows/is based on/uses that data(the string array in your case) should be invalidated(remeasured, redrawn) in order to show the user the new set of data.
Does the 3rd view item in my list view be notified?
No, the parent ListView
will be notified. When you set the adapter on a ListView
, an observer(from the ListView
) will be set for that adapter. Calling notifyDataSetChanged
on the adapter will announce that observer from the ListView
that something has happen to the data. At this moment the ListView
will recreate the rows to show the new data.
Also, how is notifyDataSetChanged() and getView() concerned ?
I'm not sure I understand what you ask. The getView
method of an adapter is used by the ListView
to obtain a new row each time this is required. When you call notifyDataSetChanged
on the adapter this will trigger the observer in the ListView
. As it's time to recreate the list, the ListView
will call the getView
method of the adapter to show the necessary number of rows(the ones visible on the screen). So each time you call notifyDataSetChanged
the getView
method will be called for the visible rows.
What does notifyDataSetChanged() do on recyclerview? why it keeps adding new data everytime i call notifyDataSetChanged()?
Your first question
What does
notifyDataSetChanged()
do onrecyclerview
?
From Docs
notifyDataSetChanged
Notify any registered observers that the data set has changed.
There are two different classes of data change events, item changes and structural changes. Item changes are when a single item has its data updated but no positional changes have occurred. Structural changes are when items are inserted, removed or moved within the data set.
means whenever you called
notifyDataSetChanged()
it callonBindViewHolder()
Your second question
why it keeps adding new data everytime i call notifyDataSetChanged()?
Because you are using adding new data in your adapterChart
using below lineadapterChart.addData(mItemsChart);
inside Your onBindViewHolder
it means whenever your onBindViewHolder
is called you are adding data in your adapterChart
Android ListView - difference between adapter.notifyDataSetChanged and using new adapter
When you call notifyDataSetChanged()
, getView()
is called the same number of times. However, since the adapter is the same, these views can be reused (i.e. passed as convertView
).
That cannot be done when supplying a new adapter, because the ListView
cannot know for sure that the new adapter uses the same layouts. So the recycler is cleared, and all rows must be created from scratch (which is far costlier than reusing them).
(This performance point is moot if you ignore the supplied convertView
and always create/inflate a new view -- but that's a bad idea anyway).
Is notifyDataSetChanged() really necessary when updating ListView
The adapter needs to know that the data has changed in order to refresh itself so it's necessary to do so. The question is why you need an alternative in the first place!
However if you need it to be more performant you can notify the specific item got changed not the whole items by using RecyclerView.Adapter's notifyItemChanged (int position) and this is not available if you still using ListView.
Android ListView notifyDataSetChanged() dont refresh the list
replace :
credentials.clear();
with :
adapter.clear()
and whenever you want adding data to the list use:
adapter.addAll(credentials)
or
adapter.insert("new data")
its must fix your problem.
last point : adapter.notifyDataSetChanged(); it not necessary because it is inside the body of adapter methods. good luck.
Android notifyDataSetChanged not working
create a method in your adapter
like:
public void updateList(){
notifyDataSetChanged()
}
and call this method when you want to refresh the list
Related Topics
How to Capture the Android Device Screen Content
Unsupportedoperationexception: Can't Convert to Dimension: Type=0X1
How to Import Existing Android Project into Eclipse
How to Set Image Button Backgroundimage for Different State
How to Call a .Net Webservice from Android Using Ksoap2
Android: How Does Bitmap Recycle() Work
Android Fragments. Retaining an Asynctask During Screen Rotation or Configuration Change
How to Launch Activity Only Once When App Is Opened for First Time
When How to First Measure a View
Strange Behavior with Android Orientation Sensor
How to Remove Application from App Listings on Android Developer Console