Цитируя документацию для AsyncTask, найденную здесь , говорится:
В идеале AsyncTasks следует использовать для коротких операций (максимум несколько секунд). Если вам нужно поддерживать работу потоков в течение длительных периодов времени, настоятельно рекомендуется использовать различные API, предоставляемые java.util.concurrent pacakge, такие как Исполнитель, ThreadPoolExecutor и FutureTask.
Возникает вопрос: почему? В doInBackground()
функции сбегает в потоке пользовательского интерфейса так , что вред есть, имея долго запущенную операцию здесь?
android
android-asynctask
user1730789
источник
источник
doInBackground
функция замораживает экран, если индикатор выполнения не используется.Ответы:
Это очень хороший вопрос, программисту Android требуется время, чтобы полностью разобраться в проблеме. Действительно, у AsyncTask есть две основные проблемы, которые связаны:
Внутри RoboSpice приложение мотиваций ( доступно на Google Play ) мы ответить на этот вопрос подробно. Он предоставит подробное представление об AsyncTasks, Loaders, их функциях и недостатках, а также познакомит вас с альтернативным решением для сетевых запросов: RoboSpice. Сетевые запросы являются обычным требованием в Android и по своей природе являются длительными операциями. Вот отрывок из приложения:
Жизненный цикл AsyncTask и Activity
AsyncTasks не следуют жизненному циклу экземпляров Activity. Если вы запускаете AsyncTask внутри Activity и вращаете устройство, Activity будет уничтожено, и будет создан новый экземпляр. Но AsyncTask не умрет. Он будет жить, пока не завершится.
И когда он завершится, AsyncTask не будет обновлять пользовательский интерфейс нового Activity. Действительно, он обновляет предыдущий экземпляр активности, который больше не отображается. Это может привести к исключению типа java.lang.IllegalArgumentException: представление, не прикрепленное к диспетчеру окон, если вы используете, например, findViewById для получения представления внутри действия.
Проблема с утечкой памяти
Очень удобно создавать AsyncTasks как внутренние классы ваших Activity. Поскольку AsyncTask необходимо будет манипулировать представлениями Activity, когда задача завершена или выполняется, использование внутреннего класса Activity кажется удобным: внутренние классы могут напрямую обращаться к любому полю внешнего класса.
Тем не менее, это означает, что внутренний класс будет содержать невидимую ссылку на свой экземпляр внешнего класса: Activity.
В конечном итоге это приводит к утечке памяти: если AsyncTask длится долго, он сохраняет активность «живой», тогда как Android хотел бы избавиться от нее, поскольку она больше не может отображаться. Действие не может быть собрано мусором, и это центральный механизм для Android для сохранения ресурсов на устройстве.
Использование AsyncTasks для длительных операций - действительно очень плохая идея. Тем не менее, они подходят для короткоживущих, таких как обновление View через 1 или 2 секунды.
Я рекомендую вам загрузить приложение RoboSpice Motivations , оно действительно подробно объясняет это и предоставляет образцы и демонстрации различных способов выполнения некоторых фоновых операций.
источник
Потому что
AsyncTask
по умолчанию используется пул потоков, который вы не создавали . Никогда не привязывайте ресурсы из пула, который вы не создавали, поскольку вы не знаете, каковы требования к этому пулу. И никогда не привязывайте ресурсы из пула, который вы не создавали, если документация для этого пула говорит вам не делать этого, как здесь.В частности, начиная с Android 3.2, пул потоков, используемый по
AsyncTask
умолчанию (для приложений, для которыхandroid:targetSdkVersion
установлено значение 13 или выше), имеет только один поток в нем - если вы свяжете этот поток на неопределенный срок, ни одна из ваших задач не будет выполняться.источник
Service
просто используйте aThread
или aThreadPoolExecutor
.TimerTask
это стандартная Java, а не Android.TimerTask
от него отказались в пользуScheduledExecutorService
(который, несмотря на свое название, является частью стандартной Java). Ни один из них не привязан к Android, поэтому вам все равно нужна служба, если вы ожидаете, что эти вещи будут работать в фоновом режиме. И вам действительно следует подуматьAlarmManager
, от Android, так что вам не нужна служба, которая просто следит за тиканьем часов.Задача Aysnc - это специализированные потоки, которые по-прежнему предназначены для использования с графическим интерфейсом ваших приложений, но при этом сохраняют ресурсоемкие задачи потока пользовательского интерфейса. Поэтому, когда такие вещи, как обновление списков, изменение ваших представлений и т. Д., Требуют от вас выполнения некоторых операций выборки или операций обновления, вы должны использовать асинхронные задачи, чтобы вы могли держать эти операции вне потока пользовательского интерфейса, но обратите внимание, что эти операции все еще каким-то образом связаны с пользовательским интерфейсом. .
Для более длительных задач, которые не требуют обновления пользовательского интерфейса, вы можете вместо этого использовать службы, потому что они могут работать даже без пользовательского интерфейса.
Поэтому для коротких задач используйте асинхронные задачи, потому что они могут быть убиты ОС после того, как ваша порождающая активность умирает (обычно не умирают в середине операции, но завершают свою задачу). А для долгих и повторяющихся задач используйте вместо этого сервисы.
для получения дополнительной информации см. темы:
AsyncTask дольше нескольких секунд?
а также
AsyncTask не остановится, даже если действие было уничтожено
источник
Проблема с AsyncTask в том, что если он определен как нестатический внутренний класс действия, он будет иметь ссылку на действие. В сценарии, когда действие контейнера асинхронной задачи завершается, но фоновая работа в AsyncTask продолжается, объект действия не будет собираться мусором, поскольку на него есть ссылка, это вызывает утечку памяти.
Решение исправить это - определить асинхронную задачу как статический внутренний класс активности и использовать слабую ссылку на контекст.
Но все же рекомендуется использовать его для простых и быстрых фоновых задач. Чтобы разработать приложение с чистым кодом, лучше использовать RxJava для запуска сложных фоновых задач и обновления пользовательского интерфейса с их результатами.
источник