случайные ошибки одновременного падения Android - PullRequest
0 голосов
/ 24 февраля 2011

Я пишу приложение с поддержкой болтливой сети и для улучшения взаимодействия с пользователем я использую все виды конструкций параллелизма.Информация, поступающая из сети, содержит текстовые элементы и URL-адреса для изображений.В настоящее время я извлекаю изображения блокирующим способом, не создавая новую ветку для извлечения изображений.Это работает хорошо, но я понял, что могу сделать вещи намного быстрее, создавая другой поток для получения изображений.Я остановился на пуле потоков с двумя рабочими потоками для выполнения этой задачи, но теперь у меня периодически возникают проблемы с падением приложения.Кажется, это происходит случайно, и я не знаю, что именно происходит не так.Итак, вот как я сейчас делаю:

  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: поток завершается с необработанным исключением (группа = 0x4001d800) 02-23 21: 30: 20.342: ОШИБКА / AndroidRuntime (1209): ИСКЛЮЧИТЕЛЬНОЕ ИСКЛЮЧЕНИЕ: главная 02-23 21: 30: 20.342: ОШИБКА / AndroidRuntime (1209):java.lang.IllegalStateException: содержимое адаптера изменилось, но ListView не получил уведомление.Убедитесь, что содержимое вашего адаптера не изменено из фонового потока, а только из потока пользовательского интерфейса.[в ListView (16908298, класс android.widget.ListView) с адаптером (класс android.widget.HeaderViewListAdapter)] 02-23 21: 30: 20.342: ERROR / AndroidRuntime (1209): в android.widget.ListView.layoutChildren (ListView.java: 1492) 02-23 21: 30: 20.342: ОШИБКА / AndroidRuntime (1209): at 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 (собственный метод) 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

1 Ответ

3 голосов
/ 24 февраля 2011

Похоже, что когда элемент становится доступным, вы обновляете адаптер списка из рабочего потока в AsyncTask. Тот же адаптер используется в потоке пользовательского интерфейса для отображения списка. Это может привести к случайным сбоям, поскольку вы, возможно, обновляете адаптер списка для следующего элемента, пока он все еще отвечает на более раннюю notifyDataSetChanged().

Лучший способ обновить адаптер списка - использовать обработчик для публикации исполняемого файла в потоке пользовательского интерфейса, который обновит адаптер списка и вызовет notifyDataSetChanged().

При обновлении изображения может происходить похожая вещь.

Как общая стратегия, любая структура данных, от которой зависит пользовательский интерфейс, должна обновляться в потоке пользовательского интерфейса. Это имеет тенденцию быть более безопасным вокруг. Альтернативная стратегия состоит в том, чтобы тщательно синхронизировать критические участки кода, но сделать это гораздо сложнее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...