ww050312
V2EX  ›  问与答

请教一下, Android 里的 ListView 如何实时更新数据并逐条显示?

By ww050312 at 2020 年 11 月 30 日 · 3456 次点击
想做类似微信对话那种形式的 listview,但是是后台接受到十几个数据后依次添加到 arraylist 里,每次 arraylist.add(item)之后就调用 notifyDataSetChanged()方法想让视图上出现新的一行,3s 之后再添加第二行,可是用 for loop 之后发现就算我在每次 notifyDataSetChanged 之后延迟 3s 也会变成 3s 之后所有数据一次性出现在视图上……已经彻底懵了。请问一下有什么可行的方式实现吗?
第 1 条附言  ·  2020 年 11 月 30 日
已经 ok 了 感谢
32 条回复  •  2020-12-01 09:33:47 +08:00
ww050312
   1
ww050312  
OP
   2020 年 11 月 30 日
upup
ww050312
   2
ww050312  
OP
   2020 年 11 月 30 日
upupup
SelectLanguage
   3
SelectLanguage  
   2020 年 11 月 30 日
有刷新单条数据的方法
kop1989
   4
kop1989  
   2020 年 11 月 30 日
意思是,不管真实的数据来多少条。ListView 你也想每隔 3 秒冒出一条来?

那就需要你用一个单独的线程去每隔三秒添加一条记录给你 adapter 绑定的数据源。
然后调用你说的 notifyDataSetChanged();
ww050312
   5
ww050312  
OP
   2020 年 11 月 30 日
@SelectLanguage 这个我会,或者用按钮单击逐条添加数据也会,就是不知道怎么自动化逐条添加 orz 包括 debug 的时候它也是一直黑屏,直到整个 for loop 执行完毕后才能出现完整视图 同时 list view 也就一次性显示了所有数据……
kop1989
   6
kop1989  
   2020 年 11 月 30 日
换句话说,就是不要把你接收消息的 List ( A )当作 adapter 的数据源。
要单独 new 一个 List ( B )作为 adapter 的数据源,然后每隔三秒,从 A 取一条加入 B 。

当然,还有其他做法(不建议这么做),比如自定义 Adapter,然后重写 setView (名字不确定)方法,在 setView 方法里处理应该显示的 item 数量。然后外侧每隔三秒 notifyAll();
ww050312
   7
ww050312  
OP
   2020 年 11 月 30 日
@kop1989 orz 对的 可以请教一下更详细的操作吗,刚刚查了一下安卓插入线程的方式看得很晕,是要用 Handler 吗?
kop1989
   8
kop1989  
   2020 年 11 月 30 日
@ww050312 #7 可以搜索关键词《 java 定时器》来解决你的问题。(当然,前提你是用的 java 来开发 android,用其他语言就搜其他语言的定时器)
evitceted
   9
evitceted  
   2020 年 11 月 30 日
实在不懂需求
ww050312
   10
ww050312  
OP
   2020 年 11 月 30 日
@evitceted 就类似微信不断从顶端弹出消息那种(?
zeropercenthappy
   11
zeropercenthappy  
   2020 年 11 月 30 日   ❤️ 1
按楼上说的,数据源不要直接使用,给你的 adapter 重新 new 一个集合当作数据源,每 3s 从原始数据源里取一条数据。
Android 里有一个很方便的倒计时类 CountDownTimer,你实在不会的话可以考虑用它。
。总时长可以用 Long.MAX_VALUE,步长按你的需要设置为 3000ms 。
在 onTick 回调里取数据就行了,不需要你关心子线程主线程的事。
kop1989
   12
kop1989  
   2020 年 11 月 30 日
@evitceted #9 这种在包装 app 热度的时候很常见。比如一些社交类 app,没准机器人给你发的信息就是直接一个接口取下来的。但是你展示的时候肯定要一会冒出来一个。否则就太假了。
ww050312
   13
ww050312  
OP
   2020 年 11 月 30 日
@kop1989 所以大概过程就是在定时器里放一个任务,同时在定时器激活前要 new 一个 list (全局变量吗?)然后在定时器内:不断将数据加到新的 arraylist 里面,同时 notifyDataSetChanged()。
我对 NotifyDataSetChanged 这个函数的功能很懵,看源代码像是同步但是搜出来又很多说它异步。
非常感谢!!
ww050312
   14
ww050312  
OP
   2020 年 11 月 30 日
@zeropercenthappy !好的,立刻去尝试一下。
Porster
   15
Porster  
   2020 年 11 月 30 日
你需要准备 2 个 list,一个是网络数据 ListA 。一个是在适配器里的数据 ListB 。
每次操作只往适配器里的 ListB 增加 1 条,再调用 notifyDataSetChanged 。
如此循环 listA.size 次后,你的 ListView 才完全展示完毕
ww050312
   16
ww050312  
OP
   2020 年 11 月 30 日
@kop1989 对对,我其实就是想要这种连续的自动回复的效果……我表述能力太差了 = =
ww050312
   17
ww050312  
OP
   2020 年 11 月 30 日
@Porster 我现在就是这么操作的,但是它会在最后直接全部显示……特别迷惑的是即便我中间调用了延时,也必然是最后全部结束后才一起画出来= =
kop1989
   18
kop1989  
   2020 年 11 月 30 日
@ww050312 #13 你可以近似理解为就是一个“观察者模式”的实际范例(这么说其实不严谨),大概逻辑就是他会根据数据源的数据变化“局部刷新”ListView 的 Layout 。
具体的就不赘述了,可以自己搜索一下,应该对你对于“设计模式”的理解有帮助。
zeropercenthappy
   19
zeropercenthappy  
   2020 年 11 月 30 日
@kop1989 你扯远了

根据 #5 的回复 “包括 debug 的时候它也是一直黑屏,直到整个 for loop 执行完毕后才能出现完整视图 同时 list view 也就一次性显示了所有数据”

这应该只是个刚开始写 Android 的同学,还没有 UI 线程、子线程的概念..
Melodyer
   20
Melodyer  
   2020 年 11 月 30 日
@zeropercenthappy 对,他的代码应该是在 for 循环里面每次循环 sleep 了 3s 。简单点,楼主可以改为使用 Hadnler 来实现,每 3s 发送一个 message 来触发添加一个 item 的操作。
Melodyer
   21
Melodyer  
   2020 年 11 月 30 日
@Melodyer Hadnler --> Handler
chniccs
   22
chniccs  
   2020 年 11 月 30 日
ListView 已经不推荐使用了,推荐使用 RecycleView 可以局部刷新,另外你调用 notifyDataSetChanged 之后再延时 3 秒,这是在主线程中执行的吧?这样操作是阻塞了主线程了,所以你屏幕会卡住,延时操作需要在子线程中执行。然后到主线程中执行数据刷新。
aerzha
   23
aerzha  
   2020 年 11 月 30 日
维护一个消息队列(因为可能本次没发完下次的又来了),使用 handler postMessageDelay 定时发送一条消息,handleMessage 中从消息队列里取出一条(注意同步问题),然后插入到 listview 中,再 handler postMessageDelay 。。。。

另外,推荐使用 recyclerView,直接单条数据插入,不用重新 notifydatasetchanged
ww050312
   24
ww050312  
OP
   2020 年 11 月 30 日
@aerzha 枯了 我都不知道有这个东西 单纯 follow 我们 prof 教的东西= = 顺便问下我是自己重写的 adaptor,如果换 recycleView 的话 adaptor 变化大吗?
aerzha
   25
aerzha  
   2020 年 11 月 30 日
@ww050312 额,recyclerView 的用法, 在 Android 里算是最基础的东西了,随便网上扒篇文章,几分钟就能撸个 demo 了,adapter 的话,要使用 RecyclerView.Adapter 了
zeropercenthappy
   26
zeropercenthappy  
   2020 年 11 月 30 日
都搞错了重点了..楼主现在的问题不是 ListView 还是 RecyclerView 的问题,而是如何做到延时 3s 取数据而不阻塞主线程的问题。

楼上说的 Handler 是可行的,但是就为了这一点需求未免有点太麻烦,所以你就老老实实用我上面说的 CountDownTimer 来做就行了,把这个作业完成了之后再去研究别人说的这些东西吧
v2xiaowen
   27
v2xiaowen  
   2020 年 11 月 30 日 via Android
3 秒给 list 里 add 一个数据
ww050312
   28
ww050312  
OP
   2020 年 11 月 30 日
@zeropercenthappy 谢啦!已经成功了👌
stfu
   29
stfu  
   2020 年 11 月 30 日
@zeropercenthappy LZ 应该本身就了解 Handler 了,你拿个封装的新东西给他他更难受吧。。 而且用 Handler 比较能让新手感受到业务数据的走向。
PS LZ05 年?建议找一个 25 岁+的前辈问问较为正确的学习路径,初步判断这个年龄学 Android 和所在做的 demo,是一条错误的路径。
zeropercenthappy
   30
zeropercenthappy  
   2020 年 11 月 30 日   ❤️ 1
@stfu CountDownTimer 本质也是用 Handler 实现的。
当然本着学习的角度来说你是对的,只是我看 LZ 一脸懵的样子,再看看楼上的兄弟都扯到天边了,为了避免楼主 30 分钟 Android 开发从入门到放弃,先把解决方案给了先 haha 。
PS:不管你是学校的作业还是自己的兴趣,欢迎入坑 Android 开发。
ww050312
   31
ww050312  
OP
   2020 年 11 月 30 日
@stfu 😅啊这就是我们学校的入门安卓课(
@zeropercenthappy 嗯 谢谢
chenjiajia9411
   32
chenjiajia9411  
   2020 年 12 月 1 日
如果愿意学 Kotlin,这个需求很快就撸出来了;即使来不及(看起来只要完成课上任务就行了),花半小时看看[Paging]( https://developer.android.com/topic/libraries/architecture/paging)怎么用也能做出来了……
© 2026 V2EX · 46ms · 3.9.8.5