Course Content
-
Подготовка
-
Учимся работать с Retrofit и GSON
-
Всё вместе. Создание UI и отображение ответа от сервера
-
Использование RxJava 2.0 для создания вызовов В этом разделе вы научитесь использовать RxJava 2.0 для создания вызовов к серверу и получения ответа
Добавление RxJava 2.0 к проекту и переход от Retrofit Callback к RxJava для получения данных
Мы написали небольшое приложение, которое умеет обращаться к удаленному серверу и выводить полученные данные. Однако подход, использующий callback в Retrofit, является не очень удобным. Например, нам нужно будет сделать несколько запросов на основании ответа предыдущих. В случае со стандартным подходом наш код станет громоздким и трудно поддерживаемым. На помощь приходит библиотека RxJava.
Поэтому в этом разделе мы добавим в проект RxJava 2.0 и научимся делать запросы, используя библиотеку для реактивного программирования RxJava и RxAndroid. Если вы впервые столкнулись с библиотекой RxJava, то рекомендую пройти созданный мной видеокурс на Stepic по основам RxJava c примерами.
Код проекта вы можете скачать здесь.
Добавление зависимостей
Сначало, в проект необходимо добавить следующие зависимости
// RxJava implementation "io.reactivex.rxjava2:rxjava:2.2.17" // RxAndroid implementation "io.reactivex.rxjava2:rxandroid:2.1.1" // Для использования RxJava c Retrofit implementation "com.squareup.retrofit2:adapter-rxjava2:2.7.1"
RxAndroid – является надстройкой над RxJava, добавляющей несколько классов для использования RxJava на платформе Android. В частности, как вы знаете, в Android запрещено обращаться к серверу из главного потока. Для переключения между фоновым потоком обратно в главный поток, нам понадобится AndroidSchedulers.mainThread() который и находится в RxAndroid. Следующим шагом, после добавления нужных библиотек, необходимо изменить интерфейс, который Retrofit использует для создания запросов к серверу.
Добавление RxJava адаптера к Retrofit
Для использования RxJava необходимо добавить Retrofit адаптер, как показано ниже:
object MovieApiClient { const val BASE_URL = "https://api.themoviedb.org/3/" val apiClient: MovieApiInterface by lazy { val retrofit = Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build() return@lazy retrofit.create(MovieApiInterface::class.java) } }
Обратите внимание, мы добавили .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) в builder
Замена Retrofit Call на Single
Откройте файл MovieApiInterface.kt и замените вызов
@GET("movie/top_rated") fun getTopRatedMovies(@Query("api_key") apiKey: String, @Query("language") language: String): Call<MoviesResponse>
На следующий код:
@GET("movie/top_rated") fun getTopRatedMovies(@Query("api_key") apiKey: String, @Query("language") language: String): Single<MoviesResponse>
Обратите внимание, что мы заменили Call на Single. Single – похож Observable, но который имеет, только 2 метода: onSuccess(),onError(). То есть, используя Single, вы может, либо получить 1 значение либо получить ошибку. Single рекомендуется использовать для сетевых запросов, где как раз вы можете либо получить ответ от сервера, либо ошибку.
Теперь, чтобы получить данные в MainActivity, нам необходимо избавиться от методов Retrofit
Получение данных, используя RxJava и RxAndroid
Для получения данных в стиле Rx, необходимо заменить методы Retrofit на использование RxJava. Для этого замените код в MainActivity.kt
val topRatedMovie = MovieApiClient.apiClient.getTopRatedMovies(API_KEY, "ru") call.enqueue(object : Callback<MoviesResponse> { override fun onResponse( call: Call<MoviesResponse>, response: Response<MoviesResponse> ) { val movies = response.body()!!.results // Передаем результат в adapter и отображаем элементы recyclerView.adapter = MoviesAdapter(movies, R.layout.list_item_movie) } override fun onFailure(call: Call<MoviesResponse>, t: Throwable) { // Логируем ошибку Log.e(TAG, t.toString()) } })
Следующим образом:
// Получаем Single val getTopRatedMovies = MovieApiClient.apiClient.getTopRatedMovies(API_KEY, "ru") getTopRatedMovies .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { it -> val movies = it.results // Передаем результат в adapter и отображаем элементы recyclerView.adapter = MoviesAdapter(movies, R.layout.list_item_movie) }, { error -> // Логируем ошибку Log.e(TAG, error.toString()) } )
Давайте кратко пройдёмся по коду.
Строчка
// Получаем Single val getTopRatedMovies = MovieApiClient.apiClient.getTopRatedMovies(API_KEY, "ru")
Инициализирует источник данных Single<MoviesResponse> подписавшись на который, мы создадим запрос для получения списка популярных фильмов и получим данные. Далее, с помощью
getTopRatedMovies .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread())
переводим исполнение запроса в поток Schedulers.io() и после того, как он отработает – возвращаемся в UI поток с помощью оператора observeOn, который принимает в качестве аргумента AndroidSchedulers.mainThread(). Далее, так как мы используем Single, то у нас есть 2 варианта обработки: onSuccess и onError в каждом из которых мы соответсвенно и обрабатываем результаты. Вот и все, таким образом мы убрали использование методов обратного вызова от Retrofit и перешли к использованию RxJava. Код проекта вы можете скачать здесь.
Не забудьте присоединиться к нам в Telegram:
- в канале AndroidSchool.ru публикуются полезные материалы для Android-разработчика и скидки на продвинутые курсы
- новый чат @android_school_talk задаём вопросы и предлагаем идеи для улучшения курсов на AndroidSchool.ru
- Практический курс по программированию на RxJava 2.0 для начинающих на Stepik перейти по ссылке