Android AsyncTask для длительных операций

Высказывая документацию для AsyncTask, найденную здесь , она говорит

AsyncTasks в идеале следует использовать для коротких операций (не более нескольких секунд). Если вам нужно поддерживать потоки в течение длительных периодов времени, настоятельно рекомендуется использовать различные API, предоставляемые java.util.concurrent pacakge, такие как Исполнитель, ThreadPoolExecutor и FutureTask.

Почему мой вопрос возникает? Функция doInBackground отключается от потока пользовательского интерфейса. Так какой у нас может быть вред?

Solutions Collecting From Web of "Android AsyncTask для длительных операций"

Это очень хороший вопрос, для полного понимания проблемы требуется время как программист для Android. Действительно, у AsyncTask есть две основные проблемы:

  • Они плохо привязаны к жизненному циклу деятельности
  • Они очень легко создают утечки памяти.

В приложении RoboSpice Motivations ( доступно в Google Play ) мы подробно ответим на этот вопрос. Он даст подробный обзор AsyncTasks, Loaders, их функций и недостатков, а также представит вам альтернативное решение для сетевых запросов: RoboSpice. Сетевые запросы являются обычным требованием для Android и по своей природе работают в течение длительного времени. Вот выдержка из приложения:

Жизненный цикл AsyncTask и Activity

AsyncTasks не соответствуют жизненному циклу экземпляров действий. Если вы запустите AsyncTask внутри Activity и вы повернете устройство, действие будет уничтожено и будет создан новый экземпляр. Но AsyncTask не умрет. Он будет продолжаться до тех пор, пока он не завершится.

И когда он завершится, AsyncTask не будет обновлять пользовательский интерфейс нового действия. Действительно, он обновляет прежний экземпляр активности, которая больше не отображается. Это может привести к исключению типа java.lang.IllegalArgumentException: View не подключен к оконному менеджеру, если вы используете, например, findViewById для получения представления внутри Activity.

Проблема с утечкой памяти

Очень удобно создавать AsyncTasks как внутренние классы вашей деятельности. Поскольку AsyncTask должен будет манипулировать представлениями Activity, когда задача завершена или выполняется, использование внутреннего класса Activity кажется удобным: внутренние классы могут напрямую обращаться к любому полю внешнего класса.

Тем не менее, это означает, что внутренний класс будет содержать невидимую ссылку на свой экземпляр внешнего класса: активность.

В долгосрочной перспективе это приводит к утечке памяти: если AsyncTask длится долго, он сохраняет активность «живым», в то время как Android хочет избавиться от нее, поскольку она больше не может отображаться. Активность не может быть собрана мусором, и это центральный механизм для Android, чтобы сохранить ресурсы на устройстве.


На самом деле очень плохая идея использовать AsyncTasks для длительных операций. Тем не менее, они подходят для коротких живых, таких как обновление вида через 1 или 2 секунды.

Я рекомендую вам загрузить приложение RoboSpice Motivations , оно действительно объясняет это в глубину и предоставляет образцы и демонстрации различных способов выполнения некоторых фоновых операций.

Зачем ?

Поскольку AsyncTask по умолчанию использует пул потоков, который вы не создали . Никогда не связывайте ресурсы из пула, который вы не создали, так как вы не знаете, какие требования этого пула. И никогда не связывайте ресурсы из пула, которые вы не создали, если документация для этого пула говорит вам не об этом, как в данном случае.

В частности, начиная с Android 3.2 пул потоков, используемый AsyncTask по умолчанию (для приложений с android:targetSdkVersion установленный в 13 или более android:targetSdkVersion ), имеет только один поток: если вы связали этот поток на неопределенный срок, ни одна из ваших других задач Будет работать.

Задача Aysnc – это специализированные потоки, которые все еще предназначены для использования с графическим интерфейсом ваших приложений, но сохраняя ресурсоемкие задачи потока пользовательского интерфейса. Поэтому, когда такие вещи, как обновления списков, изменение ваших представлений и т. Д., Требуют выполнения некоторых операций выборки или операций обновления, вы должны использовать async-задачи, чтобы вы могли сохранить эти операции за пределами потока пользовательского интерфейса, но обратите внимание, что эти операции все еще связаны с пользовательским интерфейсом ,

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

Поэтому для коротких задач используйте async-задачи, потому что они могут быть убиты ОС после того, как ваша нерестовая активность погибнет (обычно не будет умирать в середине операции, но выполнит ее задачу). И для длительных и повторяющихся задач вместо этого используйте сервисы.

Для получения дополнительной информации, см. Темы:

AsyncTask дольше, чем несколько секунд?

а также

AsyncTask не останавливается, даже когда действие уничтожено