V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
ww050312
V2EX  ›  问与答

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

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

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

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

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

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

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

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