【问题标题】:android random crashing concurrency issuesandroid随机崩溃并发问题
【发布时间】:2011-02-24 05:15:50
【问题描述】:

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

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

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

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

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

这是一个 logcat 输出:

02-23 21:30:20.303:调试/AndroidRuntime(1209):关闭 VM 02-23 21:30:20.313: WARN/dalvikvm(1209): threadid=1: 线程以未捕获的异常退出 (group=0x4001d800) 02-23 21:30:20.342:错误/AndroidRuntime(1209):致命异常:主要 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: 错误/AndroidRuntime(1209): 在 android.widget.ListView.layoutChildren(ListView.java:1492) 02-23 21:30:20.342: 错误/AndroidRuntime(1209): 在 android.widget.AbsListView.onLayout(AbsListView.java:1147) 02-23 21:30:20.342: 错误/AndroidRuntime(1209): 在 android.view.View.layout(View.java:7035) 02-23 21:30:20.342: 错误/AndroidRuntime(1209): 在 android.widget.LinearLayout.setChildFrame(LinearLayout.java:1249) 02-23 21:30:20.342: 错误/AndroidRuntime(1209): 在 android.widget.LinearLayout.layoutVertical(LinearLayout.java:1125) 02-23 21:30:20.342: 错误/AndroidRuntime(1209): 在 android.widget.LinearLayout.onLayout(LinearLayout.java:1042) 02-23 21:30:20.342: 错误/AndroidRuntime(1209): 在 android.view.View.layout(View.java:7035) 02-23 21:30:20.342: 错误/AndroidRuntime(1209): 在 android.widget.FrameLayout.onLayout(FrameLayout.java:333) 02-23 21:30:20.342: 错误/AndroidRuntime(1209): 在 android.view.View.layout(View.java:7035) 02-23 21:30:20.342: 错误/AndroidRuntime(1209): 在 android.widget.LinearLayout.setChildFrame(LinearLayout.java:1249) 02-23 21:30:20.342: 错误/AndroidRuntime(1209): 在 android.widget.LinearLayout.layoutVertical(LinearLayout.java:1125) 02-23 21:30:20.342: 错误/AndroidRuntime(1209): 在 android.widget.LinearLayout.onLayout(LinearLayout.java:1042) 02-23 21:30:20.342: 错误/AndroidRuntime(1209): 在 android.view.View.layout(View.java:7035) 02-23 21:30:20.342: 错误/AndroidRuntime(1209): 在 android.widget.FrameLayout.onLayout(FrameLayout.java:333) 02-23 21:30:20.342: 错误/AndroidRuntime(1209): 在 android.view.View.layout(View.java:7035) 02-23 21:30:20.342: 错误/AndroidRuntime(1209): 在 android.view.ViewRoot.performTraversals(ViewRoot.java:1045) 02-23 21:30:20.342: 错误/AndroidRuntime(1209): 在 android.view.ViewRoot.handleMessage(ViewRoot.java:1727) 02-23 21:30:20.342: 错误/AndroidRuntime(1209): 在 android.os.Handler.dispatchMessage(Handler.java:99) 02-23 21:30:20.342: 错误/AndroidRuntime(1209): 在 android.os.Looper.loop(Looper.java:123) 02-23 21:30:20.342: 错误/AndroidRuntime(1209): 在 android.app.ActivityThread.main(ActivityThread.java:4627) 02-23 21:30:20.342: 错误/AndroidRuntime(1209): 在 java.lang.reflect.Method.invokeNative(Native Method) 02-23 21:30:20.342: 错误/AndroidRuntime(1209): 在 java.lang.reflect.Method.invoke(Method.java:521) 02-23 21:30:20.342: 错误/AndroidRuntime(1209): 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 02-23 21:30:20.342: 错误/AndroidRuntime(1209): 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 02-23 21:30:20.342:错误/AndroidRuntime(1209):在 dalvik.system.NativeStart.main(本机方法) 02-23 21:30:20.402:WARN/ActivityManager(72):强制完成活动 com.daveco.pricewatcher/.SearchActivity

【问题讨论】:

  • 你能提供你的 logcat 输出吗?

标签: android concurrency feedback crash


【解决方案1】:

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

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

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

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

【讨论】:

  • 我正在使用处理程序发布带有 notifyDataSetChanged() 的可运行文件,但我认为您可能对同时发生的更新和数据更改是正确的,所以我将开始查看那里。
  • 你对正在发生的事情是正确的。我通过移动一些碎片解决了这个问题。
猜你喜欢
  • 1970-01-01
  • 2013-04-21
  • 1970-01-01
  • 2022-01-14
  • 2013-12-24
  • 1970-01-01
  • 1970-01-01
  • 2012-10-24
  • 2023-03-20
相关资源
最近更新 更多