О фоновых "задачах"
Не так давно я увидел, что AsyncTask объявлен устаревшим. Конечно, сейчас его ещё поддерживают, но потом... Поэтому возникает вопрос: какие альтернативы он имеет? Конечно, я прочитал их названия и посмотрел их реализацию, но на первый взгляд они не кажутся такими же простыми.
- Есть ли разница между отдельным потоком (а-ля Thread, HandlerThread) и выполнением в AsyncTask.doInBackground?
Очень часто я использовал AsyncTask для того, чтобы производить длительные операции (не как это рекомендовано). Например, 'анимация' фона приложения: запускал в самом начале задачу, и она каждые полторы секунды добавляла новое число и удаляла старое. Она выполнялась всё время работы приложения вот так:
@Override
protected String doInBackground(String... strings) {
HandlerThread thread = new HandlerThread("Animation");
thread.start();
final Handler handler = new Handler(thread.getLooper());
Runnable anim = new Runnable() {
public void run() {
//Создаём новый текстовый вид, выбираем случайно число, записываем его в вид.
publishProgress(text);
handler.postDelayed(this, 1500);
};
};
handler.post(anim);
return "OK";
};
// В onProgressUpdate добавляем вид в 'корневой' Layout.
Здесь я создаю новый поток. Но возможно ли сделать это в очередном новом потоке?
- Существует ли разница в производительности? Как мне показалось, когда я смотрел варианты замены асинхронной задачи, ни одна из них не работает только в фоне. Скажется ли это на времени отклика пользовательского интерфейса?
P.S. под альтернативами я понимаю: Executor, ThreadPoolExecutor, FutureTask.
P.P.S. по моему субъективному мнению, их намного сложнее использовать.
Ответы (1 шт):
AsyncTask в лучшие для него времена являлся не самым лучшим инструментом. Да он просто в понимании, но у него много недостатокв:
Каждый раз нужно писать достаточно много кода для решения относительно простой задачи.
AsyncTasks ничего не знают о жизненном цикле. При неправильном обращении лучшее, что вы получите — утечка памяти, в худшем – сбой.
AsyncTask не поддерживает сохранение состояния прогресса и повторное использование результатов загрузки.
Threads это самая низкоуровневая абстракция для работы с потоками в Java. В Android в чистом виде их уже давно никто не использует, как впрочем и Executors, хотя со вторыми работать проще.
В Android вы можете использовать Handler-ы. Эти в свою очередь являются фреймворком андроида. Это самый низкоуровневый инструмент для работы с потоками в Android. И в целом он является предпочтительным (при условии, что вы не используете сторонние библиотеки). Он более сложен, но и дает в свою очередь больше контроля.
RXJava это сторонняя библиотека, котороая очень распространена. В ней есть огромное количество возможностей и удобная работа с потоками. И в целом она решает огромный пул проблем. НО, надо понимать несколько вещей:
При всем удобстве работы с многопоточностью, RX это не про потоки, а про асинхронность.
В нее очень высокий порог вхождения.
RX очень большая библиотека, и тянуть ее в проект только для того, чтоб сходить в рабочем потоке в базу/сеть не лучшая идея.
Корутины. Корутины это решение от JetBrains для работы с потоками в Котлине. Они просты в использовании, корутины можно запускать в огромный количествах в отличии от нативных потоков. Кот пишется как синхронный и потому его легко писать и читать. Хоть они и подключаются отдельной зависимостью это решение на уровне языка (Kotlin), а значит его можно считать нативным и уверенно пользоваться им. К тому же к корутинам уже в тесте есть библиотека Flow которая будет аналогом RX Java с теми же возможностями. Из минусов только то, что это все же свежее решение и она не зайдет в проекты с большим легаси. Ну или вам придется писать какие-то абстракции.
А вообще эта тема очень огромна и обширна и тут одним ответом StackOverflow не ограничишься.