0

我正在编写一个启用聊天网络的应用程序,并且为了改善用户体验,我正在使用各种并发构造。来自网络的信息包含文本项目和图像的 URL。我目前正在以阻塞方式获取图像,而没有产生新线程来获取图像。这工作正常,但我意识到我可以通过产生另一个线程来获取图像来使事情变得更加快捷。我选择了一个带有 2 个工作线程的线程池来处理此任务,但现在我遇到了应用程序崩溃的间歇性问题。它似乎是随机发生的,我不知道到底出了什么问题。所以这是我目前做事的方式:

  1. 用户点击搜索并生成一个新的 AsyncTask 以获取所需的信息。

  2. 在新的 AsyncTask 中,信息开始涓涓细流。只要有足够的信息可用于单个项目,我们就将项目添加到列表适配器,跳转到主线程并调用notifyDataSetChanged()以更新列表。我们还向线程池提交了一个任务来获取图像,并notifyDataSetChanged()在图像准备好后立即调用。

  3. 继续更新列表,直到没有更多要处理的项目。

我认为我的设置非常好,但我想要一些改进我做事方式的建议,以及一些追踪导致崩溃的原因的指针。

这是一个 logcat 输出:

02-23 21:30:20.303: DEBUG/AndroidRuntime(1209): 关闭 VM 02-23 21:30:20.313: WARN/dalvikvm(1209): threadid=1: 线程退出未捕获异常 (group=0x4001d800) 02 -23 21:30:20.342: ERROR/AndroidRuntime(1209): FATAL EXCEPTION: main 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): java.lang.IllegalStateException: 适配器的内容已更改,但 ListView没有收到通知。确保适配器的内容不是从后台线程修改的,而只是从 UI 线程修改的。[在 ListView(16908298, class android.widget.ListView) with Adapter(class android.widget.HeaderViewListAdapter)] 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at android.widget.ListView.layoutChildren(ListView .java:1492) 02-23 21:30:20.342: 错误/AndroidRuntime(1209): 在 android.widget.AbsListView.onLayout(AbsListView.

4

1 回答 1

3

听起来当一个项目可用时,您正在从 AsyncTask 中的工作线程更新列表适配器。在 UI 线程中遍历相同的适配器以呈现列表。这可能会导致随机崩溃,因为您可能正在为下一个项目更新列表适配器,而它仍在响应较早的notifyDataSetChanged().

更新列表适配器的更好方法是使用处理程序将可运行对象发布到 UI 线程中,该线程将更新列表适配器并调用notifyDataSetChanged().

图像更新可能会发生类似的事情。

作为一般策略,UI 所依赖的任何数据结构都应该在 UI 线程上更新。它往往更安全。另一种策略是仔细同步代码的关键部分,但这要正确得多。

于 2011-02-24T05:33:03.900 回答