2010-08-22 4 views
3

Я написал виджет домашнего экрана как ImageView, т.е. код генерирует весь виджет и записывает его в RemoteViews в виде растрового изображения. На более медленных устройствах с низкой памятью, таких как мой G1, для генерации растрового изображения может потребоваться несколько секунд, и чтобы избежать страшного закрытия силы, я переместил весь графический код в AsyncTask. Все идет нормально.Сохранение AsyncTask в условиях низкой памяти?

Однако в условиях очень низкой памяти AsyncTask легко может быть убит ОС до того, как он завершит создание растрового изображения, в результате чего на рабочем столе появится пустой квадрат. Поэтому, прежде чем создавать AsyncTask, он устанавливает будильник на данный момент + 5 секунд, и после завершения графики он сбрасывает будильник. Предполагается, что если срабатывает тревога, более чем вероятно, что процесс был убит, и мы должны установить еще один сигнал тревоги + 5 и начать снова.

Это работает, но в экстремально низких объемах памяти для рисования виджета может потребоваться несколько попыток (20 + секунд), поэтому я добавил изображение песочных часов заполнителя в качестве статического ресурса, который отображается на главном экране до тех пор, пока реальное изображение готово.

Мой вопрос в том, что это лучший способ? Есть ли способ (вежливо) попросить ОС не убивать AsyncTask до тех пор, пока она не закончится (на том основании, что убийство на самом деле приведет к еще отходов системных ресурсов)?

Я понимаю, что если процесс классифицируется как «видимый», то Android его не убьет, кроме как в крайнем случае. Но я не знаю, как пометить AsyncTask как «видимый». Я очень рад, что процесс был убит, как только он нарисовал виджет. Было бы просто, чтобы он остался жив достаточно долго, чтобы закончить.

ответ

0

Рассматривали ли вы использование IntentService для этого? В то время как ваш служебный код выполняется, он получает тот же приоритет, что и приоритет переднего плана. У него не будет достаточно тесной связи с виджетами, которые была бы AsyncTask, но я думаю, что это увеличит вероятность завершения вашего кода.

+0

Я просто пробовал это и провел несколько часов, играя с разными настройками. Я попробовал это с помощью START_STICKY, с setForeground() и с приобретением WAKE_LOCK. К сожалению, ни один из них не сохранил код в ситуациях с низкой памятью, и они не восстанавливались так же легко и быстро, как код тревоги, который я сейчас использую. – Andy

+3

Я просматривал некоторые из Android-кода Google Android, и я заметил, что когда они используют AsyncTask, они будут иногда запускать пустую службу из AsyncTask, и, согласно комментариям, это не позволяет убить задачу. Вы можете увидеть ссылку на него в этом файле по строке 670: http://android.git.kernel.org/?p=platform/packages/apps/Contacts.мерзавец; а = блоб; F = SRC/COM/Android/контакты/щ/EditContactActivity.java; ч = 3e248ea93dc8b17a0d66306aaade9ea398c32408; ПП = ГОЛОВКА – Mike

0

попробуйте использовать Сервисный класс, вы можете установить сервис как «Передний план». Вероятно, почти нулевые шансы на закрытие службы Foreground.

Кроме того, служба выполняет то же самое, что и Async.

Как только вы закончите работу, закройте службу.

1

Используйте EmptyService, привязывая его и отключая, как только работа будет выполнена, см. https://github.com/android/platform_packages_providers_calendarprovider/blob/master/src/com/android/providers/calendar/EmptyService.java. Я не уверен, что это гарантирует, что вы процесс не будет убит или просто уменьшит вероятность его убийства.

Вы также можете использовать службу переднего плана, но вам нужно будет предоставить уведомление о состоянии, см. http://developer.android.com/guide/components/services.html#Foreground.

Или вы можете использовать IntentService в качестве предложенного @Mike; хотя я не вижу в документации, что «он получает тот же самый приоритет убийства, что и задача переднего плана».