ww050312
V2EX  ›  问与答

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

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

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

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

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

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

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

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