17 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Android LiveData на Kotlin с использованием Retrofit и coroutines

Применяем Kotlin Coroutines в боевом Android-проекте

Coroutines Kotlin VS RxJava в асинхронном коде

Думаю, для тех, кто не знаком с Kotlin , стоит сказать пару слов о нем и корутинах в частности. Об актуальности изучения Kotlin говорит то, что в мае 2017 года компания Google сделала его официальным языком разработки Android.

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

Итак, для чего нужны корутины ? Если требуется скачать что-то из сети, извлечь данные из базы данных или просто выполнить долгие вычисления и при этом не заблокировать интерфейс пользователю, можно использовать корутины.

В контексте Android в задачах обеспечения асинхронности их смело можно рассматривать как конкурента RxJava . Несмотря на то, что возможности RxJava гораздо шире (это довольно объемная библиотека со своим подходом и философией), работать с корутинами удобнее, потому что они — всего лишь часть языка программирования. Задачи, решенные на RxJava с помощью операторов (специальных методов библиотеки), на корутинах реализуются намного проще — через встроенные средства языка. К тому же операторы библиотек нужно не только знать, но и понимать, как они работают, правильно выбирать и применять. Конечно, средства языка знать и правильно применять тоже нужно, но, когда речь идет о сокращении времени на разработку, стоит задуматься, насколько изучение возможности библиотеки, которую используешь для решения небольшой задачи, актуально в сравнении с изучением языка, на котором пишется весь проект.

Примеры использования Coroutines Kotlin

Поддержка корутин встроена в Kotlin, но все классы и интерфейсы находятся в отдельной библиотеке. Для их использования нужно добавить зависимость в gradle:

Небольшой пример использования:

Разберемся, что тут происходит.

longRunningMethod() — метод, который нам нужно выполнить асинхронно.

GlobalScope — жизненные рамки для корутины. В данном случае корутина будет жить, пока живо приложение, в котором она запущена. GlobalScope — конкретная реализация интерфейса CoroutineScope. Можно реализовать свой scope, например, в Activity, и это приведет к тому, что запущенные в Activity корутины будут автоматически отменяться в случае завершения или краша Activity.

launch — метод для асинхронного запуска корутины. Соответственно, метод longRunningMethod() запустится сразу же. Метод возвращает экземпляр класса Job. Этот объект можно использовать для того, чтобы, например, отменить корутину — job.cancel(). Альтернатива — метод asunc(). Он вернет Deferred — отложенную корутину, которую можно запустить позднее.

Dispatchers.IO — один из параметров метода launch(). Здесь указывается диспетчер для созданной корутины. Конкретно диспетчер Dispatchers.IO используется для фоновых задач, не блокирующих основной поток. Если указать Dispatchers.Main, то корутина будет выполняться в основном потоке.

Что имеем в итоге? Простой метод запуска асинхронного кода. Но в этом кусочке кода есть скрытые преимущества , которые не видны на первый взгляд:

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

Корутины же мы можем создавать тысячами;

  • корутину можно приостановить . Метод delay(timeout) приостановит выполнение корутины, но это никак не отразится на потоке, в котором она выполняется;
  • в отличие от RxJava, для написания асинхронного кода не надо заучивать массу операторов типа merge, zip, andThen map, flatMap и т.д. Можно просто писать код, который будет запущен асинхронно, используя минимум дополнительных методов. Для реализации более сложной логики можно применять уже знакомые языковые конструкции, такие как foreach, repeat, filter и т.д.

Когда нужен асинхронный подход

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

В своем приложении мы применяем асинхронный код. Почему? Дело в том, что общение с сервером и запросы в базу данных — довольно продолжительные операции. Пока выполняется одна, вполне можно успеть завершить еще несколько, не блокируя основной поток. Именно эту задачу и решает асинхронный подход. В случае синхронного программирования операции выполняются последовательно, т.е. следующая команда запускается только после того, как завершится предыдущая, и когда какая-нибудь из них выполняется слишком долго, программа может зависнуть. И хотя все понимают, что “зависание” вряд ли понравится пользователям, все же такую реализацию иногда можно встретить в приложениях. Повторюсь, мы решаем задачу с помощью асинхронного кода.

Читать еще:  Как очистить историю в инстаграме на андроиде. Как посмотреть и очистить историю поиска в инстаграме

Применение Coroutines Kotlin в нашем проекте

Итак, запуск абстрактного асинхронного кода — это хорошо, но попробуем решить более насущную задачу. Допустим, надо сделать запрос на сервер и показать результат. Посмотрим, как это можно сделать с помощью корутин. Само скачивание будем для простоты выполнять во ViewModel, общаться с Activity будем с помощью LiveData.

Создадим класс-наследник ViewModel :

Внутри модель содержит MutableLiveData с данными пользователя, который мы получаем после авторизации. Наружу отдаем неизменяемую LiveData, чтобы никто кроме ViewModel не мог изменять данные внутри. Профиль пользователя завернут в класс Resource<>. Это утилитарный класс для удобства передачи состояния процесса во View:

Как видно, во View мы можем передавать информацию о том, завершилось ли скачивание, и если завершилось, то с ошибкой или успешно.

Запуск корутины происходит в методе login() . Он вызывает метод базового класса runCoroutine() :

У этого метода 2 параметра. Первый — типизированный экземпляр LiveData, куда будут записаны данные. Второй — код, который нужно выполнить асинхронно. В методе login() мы передаем код, который передает на сервер данные для авторизации и получает от сервера профиль пользователя.

Как работает все вместе : View получает от ViewModel LiveData, подписывается на ее изменения. Изменения могут быть трех видов: идет какой-то процесс, все завершилось с ошибкой, все завершилось успешно. В нужный момент вызывается метод login(). Затем последовательно происходит: запись в LiveData информации о том, что “идет какой-то процесс”, запрос на сервер, получение данных, запись в LiveData полученных данных. Или ошибки, если запрос на сервер не удался.

Выводы

Естественно, в одной статье невозможно раскрыть все аспекты нового инструмента в асинхронном программировании. Тем, кто заинтересовался корутинами Kotlin , можно посоветовать изучить и протестировать, к примеру, комбинирование корутин, каналы, реализацию Actor model и другие возможности.

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

Как мы видим, задачи асинхронного программирования под Android проще реализовать с помощью корутин : быстрее разработка, выше читаемость кода. Риски, конечно, тоже есть : для изучения корутин нужно некоторое время, а их возможности иногда могут не закрыть все требования задачи. Перед использованием в своем проекте рекомендуется внимательно ознакомиться с областью их применения.

Using Retrofit with Kotlin Coroutines in Android

Networking is one of the most important parts of Android Applications. One of the most popular libraries used for Networking in Android is Retrofit. The main reason Retrofit is popular among Android Networking libraries is that it reduces a lot of Boilerplate code and helps in consuming the web service easily. Also, it keeps updating with the latest trends such as compatibility with Rxjava and now, The Coroutine Support!

Welcome to our MindOrks blog on Using Retrofit with Koltin Coroutines in Android!

Starting from version 2.6.0 Retrofit supports the concept of “suspend” functions.

Before proceeding further, we would recommend our MindOrks blog for better understanding of Coroutines

In this blog we are going to understand with a sample project:

  • How to use retrofit 2.6.0 with coroutines?
  • What is the suspend keyword?
  • What is the LiveData scope in Coroutines?

We are going to understand these concepts with a project. Before discussing this topic, if you need to refresh the basics of MVVM project, please refer to our MVVM Architecture-Beginner’s Tutorial blog.

We strongly recommend you to go through the example project provided in MVVM Architecture-Beginner’s Tutorial blog as we are going to improvise on the same in this blog.

Set up a new project with Kotlin and other dependencies required

Here, we are going to set up the Android Project.

Create a Project

  • Start a new Android Studio Project
  • Select Empty Activity and Next
  • Name: Retrofit-Kotlin-Coroutines-Example
  • Package name: com.mindorks.retrofit.coroutines
  • Language: Kotlin
  • Finish
  • Your starting project is ready now

Add the following dependencies in your app level build.gradle.

Here, we can see that we have added our Retrofit and Coroutines dependencies. Since we will be launching the coroutines in the live data scope(we will be discussing this later in this blog), we add the required life cycle dependencies.

Читать еще:  Программа для распечатки документов на принтере

Project Structure

For the project, we are going to follow a beginner version of MVVM. Our package in the project will look like below, similar to our MVVM beginner’s tutorial blog.

Setting up the Utils

We set up the utils package exactly the way we set it up in our MVVM beginner’s tutorial blog.

Firstly, the Enum status class:

Now, the Resource class:

Setting up the Model

Since we will be using the same API service we have used in our MVVM beginner’s tutorial blog, we will be creating a similar model class.

Note: Here we haven’t used the @SerializedName annotation since we have declared the same variable name as that of the server response field. However, if you wish to change the variable name of the data class, you can do so by adding the annotation like follows.

Setting up the Network Layer

Now, since we are using Retrofit for Network calls, let’s create a class that provides us the instance of the Retrofit Service class.

Note: We are going to come across some new keywords such as “suspend” in this Network layer. We are going to understand this later in this blog. First, let’s set up the project.

Retrofit Service class

Retrofit Builder class:

Now, let’s create an API Helper class to help us with the ApiService call:

Our Network Layer is now set.

Since we will be using a Repository pattern, we will be linking our ApiHelper class by using a Repository class:

Setting up the ViewModel

Note: We are going to come across some new keywords such as “Coroutines”, “liveData scope”, “Dispatchers” in this ViewModel. We are going to understand this later in this blog. First, let’s set up the project.

Now, that our model and network layers are set, let’s set up our ViewModel

We will be providing our View Model from a Factory class. So let’s construct our ViewModelFactory class:

Setting up the View

Our MainActivity class:

In order to load our Recycler view, we have to create a row item type:

Note: For the ease of understanding, the dimensions are hardcoded in the provided layout files. It is strongly recommended to read the dimensions and strings from their respective dimens.xml files and strings.xml files for best coding practices.

Finally, to load our RecyclerView, we need an adapter class with a view Holder:

That’s it, our project is set up. Let’s add our internet permission in the AndroidManifest file:

Now, let’s run our project. Awesome! We can see the server response on the screen!

Understanding Retrofit with Kotlin CoroutinesNow that we have worked on the project, let’s understand two key things:

Suspend

The suspend functions can only be called from Coroutines. Adding the keyword suspend helps the coroutine to suspend (pause), perform the required job on a network thread (if Dispatchers.IO) is used, wait for the response, and then resumes from where it left off once the response is available. In our example code, the ViewModel class:

Here, the getUsers function of the MainRepository class is a suspend function, and hence, only once the network call(which is run on another thread, in this case, the thread from Dispatchers.IO) is completed (success or error), the coroutine resumes by emitting the respective value that is obtained from the network call.

LifeCycle Scope

A LifecycleScope is defined for each Lifecycle object. LifecycleOwner could be an Activity or a Fragment. Any coroutine launched in this scope is canceled when the Lifecycle is destroyed. This helps us in avoiding memory leaks.

Here we have used liveData(Dispatchers.IO). If we observe the import statement:

Hence, the result of the function will be emitted as Live Data, which can be observed in the view (Activity or Fragment).

Project Source Code and What Next?

You can find the complete project here .

As we have done some simplifications in this project for the Beginners level, so, we can improve this project to go to the Advanced level, a few of the things which we can improve are as follows:

  • Implement Dependency Inject Framework – Dagger in the project.
  • Make ApiService Singleton and reuse the same instance for all the features.
  • Create base classes such as BaseActivity.
  • Handle all the API errors at a single place in a better way.
  • Create Interfaces for the classes wherever required.
  • Take advantage of Android KTX – Kotlin Extensions .
  • Write Unit-Test
  • and so on.
Читать еще:  Acronis True Image 2015 - инструкция по использованию

That’s it for this article!

We hope that you have understood how to use Retrofit with coroutines in a simple way!

Как использовать Котлин корутины (Kotlin Coroutines) в андроид приложении. Часть 1

Это первый курок курса о том, как использовать Котлин корутины в андроид приложении.

В этом курсе вы узнаете, как использовать Kotlin Coroutines в приложении для Android — новый способ управления фоновыми потоками (background threads), который может упростить код за счет уменьшения потребности в обратных вызовах (callbacks). Корутины, или сопрограммы — это функция Kotlin, которая преобразует асинхронные обратные вызовы для длительных задач, таких как доступ к базе данных или сети, в последовательный (sequential) код.

Чтобы на практике увидеть работу с Kotlin Coroutines и архитектурными компонентами, записывайтесь на продвинутый курс по разработке приложения «Чат-мессенжер»

Вот фрагмент кода, чтобы дать вам представление о том, что вы будете делать:

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

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

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

Что вы узнаете

  • Как вызвать код, написанный с корутинами и получить результаты.
  • Как использовать функции приостановки (suspend), чтобы сделать асинхронный код последовательным.
  • Как использовать launch и runBlocking для контроля выполнения кода.
  • Методы преобразования существующих API в корутины с использованием suspendCoroutine.
  • Как использовать корутины с Architecture Components.
  • Лучшие практики для тестирования корутин.

Что нужно знать

  • Знакомство с компонентами архитектуры ViewModel , LiveData , Repository , и Room .
  • Знакомство с синтаксисом Kotlin, включая функции расширения (extension) и лямбды.
  • Основное понимание использования потоков в Android, включая основной поток, фоновые потоки и обратные вызовы.

Для введения в Компоненты Архитектуры, см. Room with a View.

Для ознакомления с синтаксисом Kotlin см. Kotlin Bootcamp for Programmers.

Для ознакомления с основами многопоточности в Android см. Guide to background processing.

Что вам понадобится

Android Studio 3.3 (можно работать с другими версиями, но некоторые вещи могут отсутствовать или выглядеть иначе).

Приступаем к настройке

Исходный код

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

… или клонируйте GitHub-репозиторий из командной строки, используя следующую команду:

Репозиторий kotlin-coroutines содержит три разных приложения:

  • kotlin-coroutines-start — Простое приложение, чтобы изучить, как сделать свою первую корутину
  • kotlin-coroutines-repository — Проект основан на обратных вызовах, которые вы конвертируете для использования корутин.
  • kotlin-coroutines-end — Проект с корутинами уже добавлен

Запуск приложения

Во-первых, давайте посмотрим, как выглядит исходный пример приложения. Следуйте этим инструкциям, чтобы открыть образец приложения в Android Studio.

  1. Если вы загрузили zip-файл kotlin-coroutines, распакуйте его.
  2. Откройте проект kotlin-coroutines-start в Android Studio.
  3. Нажмите кнопку Run и выберите эмулятор или подключите устройство Android, которое должно поддерживать Android Lollipop (минимальный поддерживаемый SDK — 21). Экран Kotlin Coroutines должен появиться:

Это стартовое приложение использует потоки, чтобы отобразить снэк-бар через секунду после нажатия в любом месте экрана. Попробуйте сейчас, и вы должны увидеть «Hello, from threads!» после небольшой задержки В первой части этого курса вы конвертируете это приложение для использования корутин.

Это приложение использует компоненты архитектуры для отделения кода пользовательского интерфейса в MainActivity от логики приложения в MainViewModel. Найдите минутку, чтобы ознакомиться со структурой проекта.

  1. MainActivity отображает пользовательский интерфейс, регистрирует слушатели кнопок и может отображать Snackbar . Он передает события MainViewModel и обновляет экран на основе LiveData в MainViewModel .
  2. MainViewModel обрабатывает события в onMainViewClicked и будет общаться с MainActivity используя LiveData.
  3. Executors определяет BACKGROUND, который может запускать работу в фоновом потоке.
  4. MainViewModelTest определяет тест для MainViewModel .

Добавление корутин в проект

Чтобы использовать корутины в Kotlin, необходимо включить библиотеку coroutines-core в файл build.gradle (Module: app) вашего проекта. В текущем проекте это уже сделано.

Корутины на Android доступны как базовая библиотека, а также специальные расширения для Android:

  • kotlinx-corountines-core — Основной интерфейс для использования корутин в Kotlin
  • kotlinx-coroutines-android — Поддержка основного потока Android в корутинах
голоса
Рейтинг статьи
Ссылка на основную публикацию
Статьи c упоминанием слов: