1

知道在正常情况下,不能在后台线程中调用 ListAdapter.notifyDataSetChanged() 来更新列表视图。所以我试着像这样解决:

class mythread extends thread {
    private ListAdapter listAdapter;
    ...
    public void run() {
        listAdpater.setNotifyOnChange(false);
        listAdapter.addAll(A_LARGE_ARRAY);
    }
    ...
}

当线程完成时,它会向 UI 线程中运行的处理程序发送一条消息,该处理程序将调用 listAdapter.notifyDataSetChanged() 来更新列表视图。

它似乎工作,除了当我尝试调试它时,调试器抱怨“适配器已更改,而列表视图没有收到通知。确保只在 UI 线程中修改 adpater。”

即使我调用了 setNotifyOnChange(false),android 框架是否会监视适配器的修改?有什么办法可以解决吗?

PS。在我自己的基准测试中,通过将 listAdapter.addAll(A_LARGE_ARRAY) 移动到后台线程,它为我节省了大约 126 毫秒的执行时间,这意味着,如果我在 UI 线程中修改适配器,它将被阻塞 126 毫秒。

更新
遇到此问题的任何人,请参阅此Google I/O Lecture链接。这真的很有帮助。

4

1 回答 1

1

您可能不想这样做,您的应用程序可能会在某些设备或某些版本的 Android 上莫名其妙地崩溃,而在其他设备上却能完美运行。

请记住,每次更新相关 UI 时都会访问 listAdpater,它在 UI 线程上运行。同时,您正在另一个线程中更新相同的 listAdpater。这意味着:

  1. 如果在修改 listAdapter 时更新 UI,UI 可能会显示不正确的项目,甚至会抛出异常(取决于竞态条件和 )
  2. 在另一个线程中更新到 listAdapter 的内容可能不会更新到主线程,如果操作系统认为它适合在另一个处理器上运行另一个线程,因为没有内存屏障(同步),不能保证这两个线程会看到同样的东西

因此,对您来说最好的做法仍然是在 UI 线程上运行更改,但一次只将 A_LARGE_ARRAY 的一小部分更新为 listAdapter。

于 2013-07-09T01:32:08.857 回答