android随机崩溃并发问题

标签 android concurrency feedback crash

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

  1. 用户点击搜索,就会生成一个新的 AsyncTask 来获取所需的信息。

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

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

我认为我的设置非常好,但我想要一些改进我做事方式的建议,也许还有一些用于追踪导致崩溃的原因的指示。

这是 logcat 输出:

02-23 21:30:20.303: DEBUG/AndroidRuntime(1209): Shutting down VM 02-23 21:30:20.313: WARN/dalvikvm(1209): threadid=1: thread exiting with uncaught exception (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: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. [in 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: ERROR/AndroidRuntime(1209): at android.widget.AbsListView.onLayout(AbsListView.java:1147) 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at android.view.View.layout(View.java:7035) 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1249) 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1125) 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at android.widget.LinearLayout.onLayout(LinearLayout.java:1042) 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at android.view.View.layout(View.java:7035) 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at android.widget.FrameLayout.onLayout(FrameLayout.java:333) 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at android.view.View.layout(View.java:7035) 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1249) 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1125) 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at android.widget.LinearLayout.onLayout(LinearLayout.java:1042) 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at android.view.View.layout(View.java:7035) 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at android.widget.FrameLayout.onLayout(FrameLayout.java:333) 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at android.view.View.layout(View.java:7035) 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at android.view.ViewRoot.performTraversals(ViewRoot.java:1045) 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at android.view.ViewRoot.handleMessage(ViewRoot.java:1727) 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at android.os.Handler.dispatchMessage(Handler.java:99) 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at android.os.Looper.loop(Looper.java:123) 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at android.app.ActivityThread.main(ActivityThread.java:4627) 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at java.lang.reflect.Method.invokeNative(Native Method) 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at java.lang.reflect.Method.invoke(Method.java:521) 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at dalvik.system.NativeStart.main(Native Method) 02-23 21:30:20.402: WARN/ActivityManager(72): Force finishing activity com.daveco.pricewatcher/.SearchActivity

最佳答案

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

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

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

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

关于android随机崩溃并发问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5100645/

相关文章:

c++ - 如何处理多个源队列消息类型

silverlight - WP7应用程序的反馈表

android - 如何在以sd卡为资源的 ListView 中为每一行设置缩略图?

android - 如何在使用 MockWebServer 时使用 Dagger 2.0 支持多个端点

Android:在其他 Activity 的 WebView 上加载 url

java - 为什么要对两个 volatile 变量进行重新排序?

android - float 操作按钮阻挡其他组件

java - JBoss 缓存配置

ios - 我可以通过 APNS 反馈检测用户是否删除设备吗?

java - 设置默认电子邮件或其他地址以获取用户反馈