在后台线程中修改适配器

时间:2013-07-09 01:04:35

标签: android

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

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

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

它似乎工作,除非我尝试调试它,调试器抱怨类似“适配器已更改,而listview没有收到通知。请确保您只在UI线程中修改adpater。”< / p>

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

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

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

1 个答案:

答案 0 :(得分:1)

你可能不希望以这种方式做事,你的应用程序可能会在某些设备或某些版本的Android上出现莫名其妙的错误,同时在其他设备上完美运行。

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

  1. 如果在修改listAdapter时更新了UI,则UI可能会显示甚至抛出异常的错误项目(取决于竞争条件和)
  2. 在另一个线程中更新到listAdapter的内容可能无法更新到主线程,如果操作系统认为它适合在另一个处理器上运行其他线程,因为没有内存屏障(同步),不能保证这些两个线程会看到同样的事情
  3. 因此,最好的操作方法仍然是在UI线程上运行更改,但一次只能将A_LARGE_ARRAY的一小部分更新为listAdapter。