I have a background thread loading data which I want to display in an Android ListView. The data changes very often (i.e. 1-2 times per second). Sometimes the number of rows in the dataset changes too (but certainly not as often as the data in the cells changes).
There are two ways to update the data in the cells, as far as I can tell:
Have the background thread notify the UI thread that new data is ready, and the UI thread can then call BaseAdapter.notifyDataSetChanged(). However, I have read in more than one place that if that method is called often, it will be slow, because the ListView has to restructure all of its subviews Views.
If the dataset count has not changed, I could possibly find all of the visible ListView cells that are associated with the changed data, and update the values manually without calling notifyDataSetChanged(). This would probably work, but I think its unfortunate that I have to update the views manually when the List Adapter is supposed to handle the update notifications and mechanisms for me when I notify it. This method also won't work if the dataset count changes over time (i.e. not only is the data within each cell of the ListView changing, but the total number of cells in the ListView can grow or shrink based on the background thread supplying realtime data).
I would certainly appreciate thoughts from others who have implemented this scenario, and how they optimized code simplicity and most importantly, performance.
I experimented with ListView
, and you essentially have to update the ListView
cells manually without calling notifyDataSetChanged()
if you have realtime data and you want the ListView
to update with better performance.
notifyDataSetChanged()
causes the ListView
to rebuild its entire View
hierarchy is very slow if you are calling it frequently (i.e. once every second).
Note (2014). This DOES NOT APPLY if you are using normal modern ListView with a ViewHolder pattern. You simply call 'notifyDataSetChanged' and that's all there is to it. It is incredibly efficient as Android knows to only update the cells on the screen.
I implemented a scheme where if my data set size changed from one update to the next, I call notifyDataSetChanged()
. If the data set size remained constant from one update to the next (such that the number of cells in the ListView
is the same as before when a redraw of the data is needed), then I iterate over the ListView.getFirstVisiblePosition()
: getLastVisiblePosition()
, and update the visible cells only.