asynctask android чем заменить

Замена AsyncTask в приложении

Класс AsyncTask в Android является крайне полезным, поскольку он предоставляет удобный интерфейс для реализации асинхронных операций.

Класс AsyncTask позволяет запускать команды в фоновом режиме и возвращать результат в основной поток. Он также сообщает о ходе выполнения задач.

TypeOfVarArgParams передается в метод doInBackground() в качестве входного. ProgressValue используется для информации о ходе и ResultValue должен быть возвращен из doInBackground() и передан в onPostExecute() в качестве параметра. Метод doInBackground() содержит основной код, который должен выполняться в фоновом потоке. Метод onPostExecute() синхронизируется с потоком пользовательского интерфейса и передаёт в него результат работы. Этот метод вызывается тогда, когда метод doInBackground() прекращает выполнение операций.

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

Объясняется это тем, что, пока выполняются длительных по времени операции в методе класса doInBackground(), на активности могут произойти изменения вплоть до её уничтожения или смены на другую активность, что приведёт к нежелательным утечкам. Всё потому, что AsyncTask зависит от контекста активности, что и позволяет ему возвращать результат работы в UI-поток.

Напишем, к примеру, приложение, которое через AsyncTask загружает картинку из Интернета и размещает в ImageView.

Код AsyncTask-а в данном случае выглядит следующим образом:

И вызываться он будет при нажатии кнопки:

Если изображение достаточно маленького размера и интернет-соединение стабильно, выполнение этих операций хоть и не желательно, но не вызовет особых проблем. Однако если изображение окажется слишком большим, то пользователь может не дождаться выполнения и сделать что-либо (свернуть приложение, перевернуть экран, запустить новый AsyncTask). В случае переворота экрана активность будет создана заново и результат операций не будет доставлен до активности, поскольку imageViewReference.get() вернёт null.

В теории реально написать приложение так, чтобы AsyncTask обрабатывал подобные случаи как положено, однако это сделает код негибким и неудобным. Поэтому проще будет воспользоваться более простыми средствами, такими как Thread и Runnable.

Так же, как и AsyncTask, класс Thread реализовывает асинхронное выполнение задач в отдельном потоке. Для того, чтобы получать доступ из потока, нужно использовать класс Handler. Handler регистрируется в потоке, в котором он был создан. Он предоставляет канал для передачи данных между UI-потоком и Thread. Данные, которые отправляются через Handler, могут быть экземплярами классов Message или Runnable. Handler особенно полезен, если вы хотите передать данные в основной поток несколько раз.

Реализуем ту же загрузку изображения этим способом.

Такой способ не будет вызывать утечку контекста и выглядит более удобным для больших операций.

Таким образом, можно сказать, что каждый из способов полезен, если речь заходит об асинхронных операциях, однако нужно помнить, что AsyncTask подходит для единоразовых маленьких операций, не связанных с сетью, а Thread для всех остальных. Если же вам нужно будет выполнять Thread несколько раз, то лучше использовать класс HandlerThread, реализация которого была описана в одной из предыдущих статей.

Замена AsyncTask в приложении : 5 комментариев

То есть вы считаете, что экземпляр интерфейса Runnable не захватывает imageView, который в свою очередь указывает на Context — и вы считаете, что это не может привести к утечке памяти?)

Правильно понимаю, что у AsynTask есть преимущество в completed из коробки, в отличие от Thread?

А что будет если метод run() завершит свою работу именно в тот момент, когда будет пересоздаваться активити или фрагмент и, например, imageView или какой-то другой элемент экрана, который мы хотим использовать по результату работы Thread, еще не инициализирован (null). Тогда, по идее, прорвется NullPointerException.

Как использование такого подхода соотносится с жизненным циклом активити или фрагмента?

почему вместо того, чтобы изобретать велосипед не использовать `AsyncTaskLoader`?

AsyncTaskLoader имеет свои недостатки, при определенных условиях он может не выполниться никогда.

Источник

Что использовать вместо AsyncTask для обновления пользовательского интерфейса для длительных операций

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

Во-первых, я хотел использовать AsyncTask, но потом обнаружил, что он не должен использоваться с длительными операциями, которые, по моему мнению, ищут файловую систему. Из документов

AsyncTasks идеально подходит для коротких операций (максимум на несколько секунд).

Их совет заключается в использовании Executor, ThreadPoolExecutor и FutureTask. Но примеры не указаны. Итак, что именно нужно делать, чтобы правильно реализовать это? Может ли кто-нибудь дать мне пример? Я не знаю, должен ли я иметь какой-то частный класс, который расширяет AsyncTask и ставит метод run внешнего класса на метод doInBackground или что-то в этом роде.

Вы можете использовать поток:

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

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

Вы можете использовать обработчики:

Основная идея заключается в создании нового Thread который использует Handler для обновления пользовательского интерфейса (потому что вы не можете обновлять ui из потока, который не является потоком пользовательского интерфейса).

Официальные документы:

Я настоятельно рекомендую использовать Loaders:

Они были построены поверх AsyncTasks, чтобы упростить управление AsyncTasks изнутри Activities.

Если это то, что должно продолжаться, даже когда действие было закрыто (фоновая операция), вы должны использовать службу, к которой вы привязываетесь в Activity. См. Документацию по локальной службе.

Источник

Android AsyncTask API deprecating in Android 11.What are the alternatives?

Google is deprecating Android AsyncTask API in Android 11 and suggesting to use java.util.concurrent instead. you can check out the commit here

17 Answers 17

Now people will have the opportunity to sanitize their code.

Based on this code, Progress is actually not needed, and there is a String input + MyPojo output.

This is actually quite easy to accomplish without any use of AsyncTask.

Читайте также:  какой значок был у немцев

How to pass in the String? Like so:

This example used a single-threaded pool which is good for DB writes (or serialized network requests), but if you want something for DB reads or multiple requests, you can consider the following Executor configuration:

You can directly use Executors from java.util.concurrent package.

I also searched about it and I found a solution in this Android Async API is Deprecated post.

Unfortunately the post is using Kotlin, but after a little effort I have converted it to Java. So here is the solution.

Pretty simple right? You can simplify it little more if you are using Java8 in your project.

Still, it cannot defeat kotlin terms of conciseness of the code, but better than the previous java version.

Hope this will help you. Thank You

One of the simplest alternative is to use Thread

If your project supports JAVA 8, you can use lambda

According to the Android documentation AsyncTask was deprecated in API level 30 and it is suggested to use the standard java.util.concurrent or Kotlin concurrency utilities instead.

Using the latter it can be achieved pretty simple:

Create generic extension function on CoroutineScope :

Use the function with any CoroutineScope :

In Activity or Fragment :

To use viewModelScope or lifecycleScope add next line(s) to dependencies of the app’s build.gradle file:

At the time of writing final LIFECYCLE_VERSION = «2.3.0-alpha05»

UPDATE:

Also we can implement progress updating using onProgressUpdate function:

Using any CoroutineScope (see implementations above) we can call it:

Use this class to execute background task in Background Thread this class is work for all android API version include Android 11 also this code is same work like AsyncTask with doInBackground and onPostExecute methods

After copying the above class, you can then use it with this:

Here I created a Alternative for AsyncTask using Coroutines which can be used same as AsyncTask without changing much code base in your project.

Create a new Abstract class AsyncTaskCoroutine which takes input parameter and output parameter datatypes of-course these parameters are optional 🙂

InCase if you need to send pass params

Android deprecated AsyncTask API in Android 11 to get rid of a share of problems to begin with.

So, what’s now?

Why Coroutines?

Google recommends using Java’s Concurrency framework or Kotlin Coroutines. but Rxjava end to have much more flexibility and features then java concurrency so gained quite a bit of popularity.

Just replace the whole class with this Thread and put it in a method to pass variables

and in Fragment add the Context to the runOnUiThread() methode:

I actually wrote two Medium stories about it:

The first one is with Java and a workaround with Runnable, the second is a Kotlin and coroutines solution. Both are with code examples of course.

It only works when the app is running (more specifically the activity which scheduled the task), but it’s capable of updating the UI after the background task was completed

EDIT: My AsyncTask no longer reqires Activiy to function.

You can use this custom class as an alternative of the AsyncTask<>, this is the same as AsyncTask so you not need to apply extra efforts for the same.

How to use it? Please follow the below examples.

With lambda expressions

Without lambda expressions

Note: Don’t forget to shutdown executors service

You can migrate to next approaches depends your needs

The accepted answer is good. But. I didn’t see cancel() method implementation

So my implementation with possibility to cancel the running task (simulating cancellation) is below. Cancel is needed to not run postExecute() method in case of task interruption.

Example of using this class:

HandlerThread can be used as an alternative of AsyncTask. They are long-running threads. An example of HandlerThread is below:

You can create two handler objects. One of them will be used to send message from workerThread to UI Thread.

Also, remember HandlerThreads run outside of your activity’s lifecycle, so they need to be cleaned up properly or else you will have thread leaks. You can use quit() or quitSafely() methods in onDestroy() of Activity to prevent thread leaks.

Источник

Несколько AsyncTask одновременно или альтернатива

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

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

Где я что неправильно понял? Если все правильно понял, то можно ли это как-то исправить? Если нельзя исправить, то как другими путями сделать два одновременно выполняющихся в background цикла?

Потоки, asyncTask или thread?
Мне нужно отправить запрос на сервер и загрузить с него инфу в мой ListFragment(данные на сервере.

Asynctask или loader для сетевых запросов?
Что с точки зрения архитектуры приложения следует использовать для обращения к серверу? asynctask.

Одновременно несколько циклов или таймеров.
Есть прога которая записывает в файл определенные данные по нажатию кнопки. Тоесть если мы.

Timof, так много в жизни используют вещей которые никто не использует что я устал считать 🙂

Если хотя бы один из потоков запустишь так

Выполнение одновременно несколько sql запросов одновременно
Здравствуйте. Есть проблема! Пролистал много сайтов и форумов и толком ничего не нашел. Суть.

Есть в JS или JQ альтернатива print_r() или var_dump()?
Есть в JS или JQ альтернатива print_r() или var_dump()? или как ещё можно посмотреть что в.

Читайте также:  control plane cisco что это

Запись в файл в несколько проходов (альтернатива безвозвратному удалению с носителя)
Вопрос в следующем, мне необходимо открыть файл с диска, допустим я его открываю fopen и заполняю.

Несколько программ одновременно
Здравствуйте, уважаемые форумчане. Вопрос такой. В CODE BLOKS я одновременно могу держать в левом.

Источник

Класс AsyncTask

Создание новой асинхронной задачи

Класс AsyncTask предлагает простой и удобный механизм для перемещения трудоёмких операций в фоновый поток. Благодаря ему вы получаете удобство синхронизации обработчиков событий с графическим потоком, что позволяет обновлять элементы пользовательского интерфейса для отчета о ходе выполнения задачи или для вывода результатов, когда задача завершена.

Напрямую с классом AsyncTask работать нельзя (абстрактный класс), вам нужно наследоваться от него (extends). Ваша реализация должна предусматривать классы для объектов, которые будут переданы в качестве параметров методу execute(), для переменных, что станут использоваться для оповещения о ходе выполнения, а также для переменных, где будет храниться результат. Формат такой записи следующий:

Если не нужно принимать параметры, обновлять информацию о ходе выполнения или выводить конечный результат, просто укажите тип Void во всех трёх случаях. В параметрах можно использовать только обобщённые типы (Generic), т.е. вместо int используйте Integer и т.п.

Соответственно, варианты могут быть самыми разными. Вот несколько из них

Для запоминания можно смотреть на схему.

Каркас реализации AsyncTask, в котором используются строковой параметр и два целочисленных значения, нужных для оповещения о выполнении работы и о конечном результате:

У AsyncTask есть несколько основных методов, которые нужно освоить в первую очередь. Обязательным является метод doInBackground(), остальные используются исходя из логики вашего приложения.

На заметку: Несмотря на то, что студия генерирует строки super.onPreExecute() и super.onPostExecute() для соответствующих методов, вы их можете удалить. В исходниках суперкласса методы ничего не делают (это просто заглушка), поэтому во многих примерах в интернете они опущены. Пусть вас это не пугает.

Простой пример для знакомства. Кот полез на крышу

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

Выведем на экран слово Полез на крышу в методе onPreExecute(), эмулируем тяжёлый код в методе doInBackground(), выведем на экран слово Залез в методе onPostExecute().

Создадим новый проект и добавим на экран кнопку, индикатор прогресса и текстовую метку:

Сначала напишем код, а потом будет объяснение к нему.

Запустите проект и нажмите на кнопку. Сначала появится текст «Кот полез на крышу», который через 5 секунд сменится надписью «Кот залез на крышу». Индикаторе прогресса при этом будет постоянно крутиться.

В методе onPreExecute() мы устанавливаем начальный текст перед выполнением задачи.

В методе doInBackground() идёт имитация тяжёлой работы. Напоминаю, что здесь нельзя писать код, связанный с пользовательским интерфейсом. Ради интереса поместите в методе строчку:

Студия будет ругаться и не позволит запустить приложение.

В методе onPostExecute() мы выводим сообщение, которое появится после выполнения задачи.

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

На данный момент для избежания конфликтов можно скрыть кнопку в методе onPreExecute() и показать её снова в onPostExecute():

Сама задача CatTask (объект AsyncTask) создаётся в UI-потоке. Также в UI-потоке вызывается метод объекта execute()

Кстати, коты прислали фотографию, которая объясняет, зачем они лезут на крышу. Интересно, откуда они узнали про эту статью?

Использование параметров

Для первого примера мы не использовали параметры. Наша задача была показать сообщения до и после выполнения задачи. Но часто нам необходимо знать промежуточные результаты выполняемой задачи. Например, мы хотим знать, что кот сейчас на втором этаже и ему осталось ещё двенадцать (бедный кот).

Когда мы создавали свой класс CatTask, то использовали угловые скобки, в которых необходимо указать три типа данных:

Во втором примере попробуем воспользоваться ими.

Начнём со второго параметра, который отвечает за промежуточные данные. Итак, нам нужно знать текущий этаж, на котором находится кот. Если дом 14-этажный, то у нас должны быть значения от 1 до 14 типа Integer:

Метод onPreExecute() оставляем без изменений, здесь мы просто выводим сообщение о начале штурма здания.

Переходим к методу doInBackground(). Мы ещё не используем входящие данные, поэтому пока здесь используется Void. В самом методе создаётся цикл от 0 до 14 и при каждом проходе цикла увеличивается счётчик counter на единицу.

При запуске проекта, вы увидите, как в текстовом поле будут меняться числа от 0 до 14.

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

Полностью код будет следующим:

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

Изменим объявление метода doInBackground():

У метода есть входные параметры типа String. Сразу поменяем первый параметр в классе CatTask:

Теперь нужно передать в метод execute() список адресов файлов для загрузки. Метод doInBackground принимает эти данные и в цикле по одному загружает эти файлы. Дальше без изменений. После прохождения каждого этажа (загрузки каждого файла) вызывается метод publishProgress(), в который передаются данные.

В обработчике кнопки вызовем метод execute(), которому передадим набор строк, так как мы указали этот тип в угловых скобках на первом месте.

Полностью код будет следующим:

Показать код (щелкните мышкой)

В нашем примере мы не загружаем картинки, поэтому строки с адресами изображений не задействованы. В других примерах вам будет попадаться такой код.

Ещё раз закрепим материал.

Читайте также:  при какой температуре выводят утят в инкубаторе

Метод execute() вызывается в основном потоке, чтобы начать выполнение задачи. В него можно передать набор данных определенного типа. Если что-то передаём, то этот тип будет указан первым в угловых скобках при создании наследника AsyncTask.

Методы onPreExecute() и onPostExecute() вызываются системой в начале и конце выполнения задачи.

Метод publishProgress() нужен в том случае, когда требуется обрабатывать промежуточные данные. Его нужно явно вызвать в методах doInBackground(), onPreExecute() или onPostExecute(). На вход передаём промежуточные данные определенного типа. Этот тип указан вторым в угловых скобках при описании AsyncTask.

Метод onProgressUpdate() получает на вход промежуточные результаты от метода publishProgress(). Так как метод onProgressUpdate() принимает на вход набор параметров, то при передаче одного значения от publishProgress нужно взять первый элемент массива.

Осталось рассмотреть вариант использования третьего параметра.

В третьем параметре указывается тип объекта, который должен вернуться из AsyncTask. Получить его можно двумя способами:

Если мы собираемся что-то возвращать, то это надо указать в возвращаемом значении у метода doInBackground() и в входящем параметре для метода onPostExecute().

Начнём с метода doInBackground() и изменим его описание следующим образом:

Студия подчеркнёт исправленный вариант, указывая несоответствие в параметрах у класса AsyncTask. Исправим:

Теперь обратимся к методу onPostExecute(). Тип Integer должен стать входящим параметром. Поменяем объявление метода:

В нашем случае входящий параметр не несёт смысловой нагрузки, просто выведем значение в текстовом поле.

Полный код для самопроверки:

Показать код (щелкните мышкой)

Метод get()

Начнём с первого варианта. Добавим на экран активности ещё одну кнопку buttonResult с надписью «Получить результат»:

Добавим код для обработчика кнопки:

Запустите приложение, далее запустите задачу нажатием первой кнопки, дождитесь окончания задачи и нажмите вторую кнопку. Во всплывающем сообщение вы увидите то же число «2012», который возвращает метод onPostExecute().

А что случится, если задача находится в стадии выполнения, а мы вызовем метод get()? Давайте проверим.

Запустим снова приложение, нажмём на первую кнопку для запуска задачи и, не дожидаясь окончания задачи, нажмите на вторую кнопку.

Создаётся ощущение, что программа остановилась. ProgressBar перестанет обновляться, текстовые сообщения также не выводятся в TextView. Но после окончания задачи появится текст и вернётся результат. Что же произошло?. Метод get() блокирует основной UI-поток и ждёт завершения AsyncTask. Это продолжается до тех пор, пока не выполнится код в методе doInBackground(). После этого метод get() возвращает результат и освобождает поток.

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

Тайм-аут

Есть ещё реализация метода с тайм-аутом. В этом случае метод get() будет ждать указанное время, а потом сгенерирует Exception. Если же задача уже была завершена, то метод выполнится сразу и ждать ничего не будет.

Перепишем код для второй кнопки:

Смотрим, что получилось. Приложение снова подвисает, но через секунду оживает и продолжает работу. Метод get() ждёт одну секунду, и если не получает результат, то генерирует исключение TimeoutException. Мы обрабатываем исключение и выводим в лог соответствующее сообщение. А приложение продолжит выполнять задачу и после успешной обработки метода onPostExecute() выводит результат.

Метод cancel() позволяет указать на отмену уже выполняющейся задачи. У метода один boolean-параметр, который указывает, может ли система прервать выполнение потока.

Кроме того, в методе doInBackground() можно проверять метод isCancelled(). Как только мы выполним метод cancel(), метод isCancelled() будет возвращать true и мы должны завершить метод doInBackground(). Таким образом, метод cancel() служит своеобразной меткой, что задачу нужно отменить. А метод isCancelled() будет считывать результат предыдущего метода и позволет выполнит код для завершения задачи.

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

Когда мы нажимаем на кнопку «Отменить операцию», то в методе cancel() используем параметр, равный true. В методе doInBackground() при работе цикла идёт проверка отмены (метод isCancelled()). Если приложение видит, что пользователь выбрал отмену задачи, то вместо метода onPostExecute() вызывается метод onCancelled(), в котором и прописываем свою логику кода.

В Android 4.0 появился ещё один метод onCancelled(Void result), способный принимать результат от метода doInBackground().

Текущее состояние задачи

Мы можем определить, в каком состоянии сейчас находится задача. Существует три состояния:

Вы можете самостоятельно проверить, в каком состоянии находится ваша задача, добавив код в нужном месте:

Вкратце, когда вы создаёте задачу (new CatTask()), то состояние PENDING. Когда вы запускаете задачу (execute()) и задача работает, то состояние RUNNING. Когда задача завершится, то состояние FINISHED. Если вы отменили задачу, то состояние по-прежнему будет RUNNING, поэтому используйте проверку через метод isCancelled() для более точного определения состояния:

В моих опытах после отмены сначала показывало состояние RUNNING, а после повторной проверки уже показывало FINISHED, возможно состояние не сразу устанавливается.

Поворот экрана

Как вы знаете, при повороте экрана активность пересоздаётся. А что происходит с задачей? При повороте старые объекты будут потеряны, в том числе и ссылка на нашу задачу. Фактически получается, что при повороте создаётся ещё одна задача, которая начинает выполняться с самого начала, при этом где-то выполняется и старая задача.

Ситуация не совсем приятная. Для ознакомления с решениями этой задачи рекомендую почитать статью Урок 91. AsyncTask. Поворот экрана, а заодно и другие материалы с сайта, связанные с AsyncTask.

Запустить несколько задач одновременно

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

Расширенный пример. Подготовим макет экрана из пяти индикаторов прогресса.

Запускаем первый индикатор, и параллельно с ним четвёртый и пятый при помощи executeOnExecutor(). Второй и третий индикатор начнут действовать после окончания работы всех предыдущих задач.

Источник

Сказочный портал