Есть некоторое приложение, которое по запросу пользователя загружает некоторые данные из сети и отображает их. Сетевые запросы в этом приложении выполняются в отдельном потоке средствами AsyncTask
.
Ввиду того, что многие категорически советуют не использовать AsyncTask
при работе с интернетом (а выносить сетевые запросы в сервис) и возник данный вопрос.
Чуть подробнее:
Суть приложения - отображение списка (текстовых) новостей из нескольких источников.
Как это реализовано сейчас:
Есть активити с Navigation Drawer
, в котором отображается список сайтов, по клику на определенный пункт меню появляется фрагмент, содержащий RecyclerView
, куда с помощью AsyncTask
загружаются данные с выбранного сайта.
При прокрутке RecyclerView
до определенного элемента запускается AsyncTask
который подгружает в RecyclerView
следующую порцию информации и так далее (эдакий Endless RecyclerView
).
При выборе другого пункта меню, появляется другой фрагмент, но с таким же принципом работы (просто данные грузятся из другого источника).
При создании каждого из фрагментов выполняется setRetainInstance(true)
, то есть при изменении конфигурации устройства данные из AsyncTask
благополучно вернутся в нужный фрагмент.
Процесс извлечения нужной информации с сайтов организован с помощью Jsoup
.
Вопросы:
Чем плоха такая архитектура данного приложения? (в части использования AsyncTask
и в общем).
Хорошим ли тоном для данной конкретной задачи является использование AsyncTask
? Или же стоит перенести работу с сетью в сервис? (я понимаю, что не все типы сервисов работают не в главном потоке).
А если все же стоит перенести работу с сетью в сервис, то при необходимости загрузки данных запускать сервис, загружать данные, возвращать данные во фрагмент и завершать сервис? И так каждый раз?
Честно говоря, хоть и на каждом углу написано, что AsyncTask
- это плохо, я не вижу явных причин для вынесения работы с сетью в сервис в данном конкретном приложении. Но раз многие говорят, значит я чего-то не понимаю. Объясните мне это, пожалуйста.
По сути, AsyncTask
же предназначен для кратковременных задач, а у меня загружается очень небольшой объем данных (текст), и в итоге AsyncTask
как раз отрабатывает за пару секунд.
А основное назначение сервиса - это, насколько я понял, выполнение длительных фоновых задач.
Еще раз повторюсь - я не утверждаю, что в данном случае лучшим решением будет использование AsyncTask
, но и аргументов против его использования я не вижу.
А может есть какие-либо другие более правильные архитектурные решения для данной задачи?
Хоть интернет и читал (очень много читал), но буду рад как ссылкам, где описывается что-то подобное (может я пропустил), так и Вашим ответам по данной теме и Вашим мнениям по данному вопросу.
Честно говоря, хоть и на каждом углу написано, что AsyncTask - это плохо
Так говорят только те, кто не умеет их готовить. AsyncTask
вполне нормальная практика, если вы умеете справляться с пограничными кейсами: поворот экрана, уничтожени контекста и т.п.
AsyncTask
не рекомендуют использовать по большей степени потому что есть уже готовые нормальные библиотеки типо Volley, Retrofit и т.п.
Сервисы используются для тяжёлых задач или же для периодических задач.
Для задач асинхронной загрузки данных в отдельном потоке используется класс, наследующий AsyncTaskLoader<D>
вместо Loader<D>
. Класс AsyncTaskLoader<D>
является абстрактным и работает как AsyncTask. На основе этого класса вы можете реализовать абстрактный метод loadInBackground()
.
Слушатель получает информацию от загрузчика. Для этого менеджер регистрирует слушатель OnLoadCompleteListener<D>
, который прослушивает события. Когда загрузка закончилась, то вызывается метод onLoadFinished(Loader<D> loader, D result).
Чтобы загрузчик начал работать, его надо запустить. Запущенный загрузчик следит за данными, пока его не перезапустят или остановят.
Остановленный загрузчик продолжает мониторить изменения в данных, но не сообщает о них. При необходимости вы можете заново запустить или перезапустить остановленный загрузчик.
При перезапуске загрузчик не должен запускать новую загрузку данных и мониторить изменения. Его задача - освободить лишние данные. Это состояние редко используется, но в некоторых случаях оно нужно.
Ваша задача сводится к созданию собственного загрузчика, реализации метода loadInBackground()
и переопределении методов onStartLoading()
, onStopLoading()
, onReset()
, onCanceled()
, deliverResult(D results)
.
Подробнее здесь.
Вся беда обычного AsyncTask
заключается в повороте экрана, в основном.
В случае с AsyncTaskLoader
по поводу поворота экрана за Вас уже позаботились. Этот класс замечательно вписывается под Вашу задачу, но вообще я бы просто посоветовал на собственном устройстве желательно с 2G\3G (медленным интернетом) подгружать новые данные и часто поворачивать экран, при этом мониторить память на устройстве. Если даже при медленном интернете утечек не будет и\или она будет, но скажем, размером с одну активити - можете оставить Ваш вариант.
Но нужно помнить одну важную строчку из GoF - любой код претерпевает изменения.
И если Вы собираетесь и дальше улучшать функционалом приложение, то в любом случае дойдете до точки, когда элементы списка будут загружать более тяжелую информацию(фотографии, местоположение и тд).
Поэтому смотрите на потенциал, насколько необходимо будет его поддерживать.
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Виртуальный выделенный сервер (VDS) становится отличным выбором
Хочу добавить новый вектор в проект, выбираю иконку из Material icon, иконка не появляется в preview, а кнопка Next не нажимаетсяПеред этим все работало
Сделал обобщенный класс StackНужно написать класс итератор, но я не понимаю, как он должен работать
Вопрос, возникающий при переходе от изучения основы Java к программированию под Android
Можно ли как то запретить смену ориентации в приложении на устройствах с экранами меньше 7 дюймов?