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 перейти по ссылке