Pull to refresh

Опыт применения Coroutines и Retrofit2

Reading time2 min
Views22K

Что это?


Кто еще не читал документацию — настоятельно рекомендую к ознакомлению.


Что пишет джетбрейнс:


Сопрограммы упрощают асинхронное программирование, оставив все осложнения внутри библиотек. Логика программы может быть выражена последовательно в сопрограммах, а базовая библиотека будет её реализовывать асинхронно для нас. Библиотека может обернуть соответствующие части кода пользователя в обратные вызовы (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() — останавливать их выполнение


Если планируется повторное использование scope после остановки выполнения — нужно использовать job.cancelChildren() вместо job.cancel() спасибо Neikist за комментарий


При этом у нас остается возможность управлять потоками:



Подключаем retrofit2


Добавляем зависимости в градл:



Используем для примера ручку https://my-json-server.typicode.com/typicode/demo/posts


Описываем интерфейс ретрофита:



Опишем возвращаемую модель Post:



Наш BaseRepository:



Реализация PostsRepository:



Наш BaseUseCase:



Реализация GetPostsListUseCase:



Вот что получилось в итоге:



Делаем еще лучше


Я ленивое существо и не хочу каждый раз тянуть всю простыню кода, поэтому вынес нужные методы в BaseViewModel:



Теперь получения списка Posts выглядит так:



Вывод


Я использовал корутины в проде и код действительно получился чище и читабельнее.


UPD:
Описание обработки исключений Retrofit см. комментарий

Tags:
Hubs:
Total votes 14: ↑14 and ↓0+14
Comments10

Articles