我有 ListView
这表明,通过 Adapter
,数据来自全局ArrayList
.如果我想添加一个元素到这个 ArrayList
正确的方法是在主 (UI) 线程中执行此操作并立即调用 Adapter.notifyDataSetChanged()
之后,为了避免“IllegalStateException:适配器的内容已更改但ListView没有收到通知”。然而 ArrayList
在辅助线程中更改,由 Service
执行它并不总是绑定(bind)到 Activity,因此并不总是引用 Adapter
为了在主线程队列中发布这些操作。因此,当(我想)主线程运行到更改的列表中时,就会出现异常。
我看到了两种规避方法:
Adapter
由克隆支持。因此,当原始列表更改时,克隆将保持不变,直到主线程需要显示更改(例如在 Activity.onResume()
上),此时我根据原始列表更新克隆并调用 notifyDataSetChanged()
. 第二种方法的缺点似乎是明显不必要的冗余和内存开销(虽然列表不大,最多大约 500 个对象,每个对象 12 个字段)。我倾向于选择第一个,但你觉得哪个最好?如果有第三种方法,请告诉我。
最佳答案
由于您没有显示您的代码,我不知道这是否有帮助,但您是否考虑过使用 CountDownLatch
?手册页中提供了一个完美的例子,它阻止了线程的执行,直到 Latch 被释放。您可以简单地在主 Activity 中声明一个实例,并传递对 Service 和其他相关部分的引用。
由于您的服务未绑定(bind),您可以使用 BroadcastReceiver
将实例传递给服务,甚至使用 Semaphore
相反,因为最后一个是可序列化的,因此可以作为一个额外的 Intent
(不过,在这种情况下,您需要绑定(bind)服务)。
关于android - 在这种情况下如何避免 IllegalStateException : The content of the adapter has changed but ListView did not receive a notification,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21113055/