Android ListView如何实时更新动态数据?
我有一个后台线程加载我想在 Android ListView 中显示的数据。数据变化非常频繁(即每秒1-2次)。有时,数据集中的行数也会发生变化(但肯定不如单元格中的数据变化那么频繁)。
据我所知,有两种方法可以更新单元格中的数据:
让后台线程通知 UI 线程新数据已准备好,然后 UI 线程可以调用 BaseAdapter.notifyDataSetChanged()。但是,我在不止一处读到过,如果经常调用该方法,速度会很慢,因为 ListView 必须重构其所有子视图 View。
如果数据集计数未更改,我可能会找到与更改的数据关联的所有可见 ListView 单元格,并手动更新值,而无需调用 notificationDataSetChanged()。这可能会起作用,但我认为不幸的是,当列表适配器应该在我通知它时为我处理更新通知和机制时,我必须手动更新视图。如果数据集计数随时间变化(即,不仅 ListView 的每个单元格内的数据发生变化,而且 ListView 中的单元格总数可能根据提供实时数据的后台线程增长或缩小,此方法也将不起作用)。
我当然很欣赏实现此场景的其他人的想法,以及他们如何优化代码简单性以及最重要的是性能。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我尝试了
ListView
,如果您有实时数据并且想要ListView
以更好的性能进行更新。notifyDataSetChanged()
导致ListView
重建其整个View
层次结构,如果您频繁调用它(即每秒一次),则速度会非常慢。注(2014)。如果您使用带有 ViewHolder 模式的普通现代 ListView,则这不适用。您只需调用“notifyDataSetChanged”即可。它的效率非常高,因为 Android 知道只更新屏幕上的单元格。
我实现了一种方案,如果我的数据集大小从一次更新更改为下一次更新,我会调用
notifyDataSetChanged()
。如果数据集大小从一次更新到下一次更新保持不变(这样,当需要重绘数据时,ListView
中的单元格数量与之前相同),那么我会迭代ListView.getFirstVisiblePosition()
:getLastVisiblePosition()
,并且仅更新可见单元格。I experimented with
ListView
, and you essentially have to update theListView
cells manually without callingnotifyDataSetChanged()
if you have realtime data and you want theListView
to update with better performance.notifyDataSetChanged()
causes theListView
to rebuild its entireView
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 theListView
is the same as before when a redraw of the data is needed), then I iterate over theListView.getFirstVisiblePosition()
:getLastVisiblePosition()
, and update the visible cells only.我曾经使用
notifyDataSetChanged()
实现了如下代码所示的过滤器,并且没有出现任何问题。我还手动修改了列表的视图。两者都运作良好。在某些情况下,我更喜欢手动修改数据,因为它更快并且不会影响整个列表。
无论如何,视图是在需要出现在屏幕上时创建的,而在离开屏幕时会被删除,因此,如果修改用于创建视图的数据,如果用户滚动 ListView 并且视图会脱离屏幕理论上,一旦视图再次进入屏幕,就会使用新数据创建视图。
我建议您尝试下面的代码来了解
notifyDataSetChanged()
的工作原理并确定它是否适合您。xml
希望这有帮助。
I once implemented a filter like the code beolow using
notifyDataSetChanged()
and had no problems with it.I've also modified the views of a List on the go manually. Both have worked well. In some case I prefear to modify the data manually because its faster and because itdoesn't affect the whole list.
Anyway, views are created on the go when they need to apear on the screen and are deleted when they leave the screen, so if you modify the data used to create the views, if the user scrolls the ListView and the views get out of the screen, in theory, the views will be created with the new data once they come again into the screen.
I would recommend you to try the code below to understand how does
notifyDataSetChanged()
work and decide if it works for you.xml
Hope this helps.
也许你可以在 UI 线程上设置一个 Handler。您需要创建一个实现 Runnable 的类。将 ArrayList 传递给此类。在 run() 方法中,使用 ArrayList 作为参数创建适配器,然后在 ListView 上执行 setAapter。就是这样。你完成了。
要启动您的处理程序:只需从您的工作线程执行此操作: handler.Post(new MyUpdateToUI() );
就是这样。我希望它对你来说足够有效?
Maybe you can set a Handler on the UI thread. You need to create a class which implements Runnable. Pass an ArrayList to this class. In the run() method create the adaptor with the ArrayList as a parameter, then do a setAapter on the ListView. That's it. You're done.
To launch your handler : just to this from your worker thread : handler.Post(new MyUpdateToUI() );
That's it. I hope it is efficient enough for you?
我遇到了非常类似的情况,我将列表视图的文本视图存储在哈希图中,其中每个文本视图都有一个标签来识别它。当流数据到达时,我所做的就是在找到正确的数据后在文本视图上发布一个可运行的数据并立即更新它们。
然而,尽管更新是即时的,但 UI 遇到了阻力并且变得缓慢,因为我每秒更新大约 30 个文本视图。我将 Listview 放在 ViewPager 内的一个片段中,当流式传输打开时,UI 线程似乎全部被堵塞和阻塞。
因此,就 UI 线程的用户体验和性能而言,我强烈建议不要手动更新 Listview 中的 Textview
I faced a very similar situation where I stored the textviews of List View in a Hashmap where each textview had a tag to have it identified. When the streaming data arrived, all I did was post a runnable on the textview after finding the correct one and got them updated in no time.
However, though the updates were instantaneous the UI faced a drag and went sluggish as I was updating about 30 textviews per second. I had my Listview in a fragment inside a ViewPager and it seemed the UI thread was all clogged up and blocked when streaming was on.
Hence, I strongly advise against manual updating of the Textviews in a Listview as far as User experience and performance of the UI thread is concerned