[Из песочницы] Опыт применения Coroutines и Retrofit2
Что это?
Кто еще не читал документацию — настоятельно рекомендую к ознакомлению.
Что пишет джетбрейнс:
Сопрограммы упрощают асинхронное программирование, оставив все осложнения внутри библиотек. Логика программы может быть выражена последовательно в сопрограммах, а базовая библиотека будет её реализовывать асинхронно для нас. Библиотека может обернуть соответствующие части кода пользователя в обратные вызовы (callbacks), подписывающиеся на соответствующие события, и диспетчировать исполнение на различные потоки (или даже на разные машины!). Код при этом останется столь же простой, как если бы исполнялся строго последовательно.
Если говорить простыми словами — это библиотека для синхронного \ асинхронного выполнения кода.
Зачем?
Потому что RxJava уже не в моде (шутка).
Во-первых, хотелось попробовать что-то новое, во-вторых, я наткнулся на статью — сравнение скорости работы корутин и других способов.
Пример
Например, нужно выполнить операцию в фоне.
Для начала — добавим в наш build.gradle зависимость от корутин:
Используем в нашем коде метод:
Где в context — мы указываем необходимый нам thread pool — в простых случаях это IO, Main и Default
IO — для простых операций с API, операциями с БД, shared preferencies и тд.
Main — UI тред, откуда мы можем получать доступ к вью
Default — для тяжелых операций с высокой нагрузкой на CPU
(Подробнее в этой статье)
Block — лямбда которую мы хотим выполнить
В принципе на этом все, мы получаем результат cуммы квадратов от 1 до 1000 и при этом не блокируем main thread что означает — никаких ANR
Однако, если наша корутина выполняется 20 секунд и за это время мы совершили 2 поворота девайса то мы будем иметь 3 одновременно выполняющихся block. Упс.
А если мы передали в block ссылку на activity — утечка и отсутствие возможности в старых блоках выполнить операции с view. Дважды упс.
Таки что делать?
Делаем лучше
Таким образом мы получили возможность останавливать выполнение нашего кода в потоке, например, при повороте экрана.
CoroutineScope сделал возможным объединить scope всех вложенных корутин и при вызове job.cancel () — останавливать их выполнение
При этом у нас остается возможность управлять потоками:
Подключаем retrofit2
Добавляем зависимости в градл:
Используем для примера ручку https://my-json-server.typicode.com/typicode/demo/posts
Описываем интерфейс ретрофита:
Опишем возвращаемую модель Post:
Наш BaseRepository:
Реализация PostsRepository:
Наш BaseUseCase:
Реализация GetPostsListUseCase:
Вот что получилось в итоге:
Делаем еще лучше
Я ленивое существо и не хочу каждый раз тянуть всю простыню кода, поэтому вынес нужные методы в BaseViewModel:
Теперь получения списка Posts выглядит так:
Вывод
Я использовал корутины в проде и код действительно получился чище и читабельнее.