Пожалуйста, опишите ошибку

Нашли баг? Помогите нам его исправить, заполнив эту форму

Retrofit 2 + RxAndroid

Илья Михайленко
Android-разработчик

Всем привет! Это статья начального уровня, в которой я расскажу, как оперировать запросами через HTTP-клиент Retrofit и получать ответ в виде Observable. Покажу в чём преимущество этого подхода и насколько он удобный. Поехали!

Сначала подключим все необходимые зависимости.

  1. Retrofit 2
  2. Адаптер rxjava и gson-converter. Они должны быть той же версии, что и Retrofit.
    compile "com.squareup.retrofit2:converter-gson:$retrofitVersion"
    compile "com.squareup.retrofit2:adapter-rxjava:$retrofitVersion"
    
  3. Logging-interceptor для вывода логов запросов в консоль.
    compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'
    
  4. RxAndroid
  5. Retrolambda. С ней наш код будет гораздо лаконичнее.

Допустим, у нас есть готовый сервер с api. По get запросу на http://pentagon/api/users будет возвращаться некий список пользователей. По post запросу http://pentagon/api/user мы отправляем на сервер нового пользователя, по get запросу http://pentagon/api/user/{id} мы получим в ответ пользователя, чей id указали.

Пусть с сервера будет приходить следующий JSON объект User.

{
“id”: 32,
“name”: “John”,
“gender”: “male”
}

Нам нужно создать свою модель User, чтобы Retrofit с помощью своей gson converter factory смог преобразовать JSON-объект в JAVA-объект, которым мы уже сможем оперировать. Имена полей JAVA-объекта и приходящего JSON-объекта должны совпадать.

public class User {
   private long id;
   private String name;
   private String gender;

   public User(String name, String gender) {
       this.name = name;
       this.gender = gender;
   }
   public long getId() {
       return id;
   }
   public String getName() {
       return name;
   }
   public String getGender() {
       return gender;
   }
}

Теперь создадим интерфейс, в котором опишем работу с запросами. Опишем 3 метода.

public interface Api {
   @GET("users")
   Observable<ArrayList<User>> getUserList();

   @GET("user/{id}")
   Observable<User> getUser(@Path("id") long id);

   @POST("user")
   Observable<User> saveUser(@Body User user);
}

Каждый метод помечен аннотацией, соответствующей методу запроса. В скобках у нас указан url, который будет добавляться к базовому. В нашем случае базовый url — http://pentagon/api/. Далее мы описываем тип возвращаемых данных. Указываем Observable и нашу модель User. В первом методе мы указываем ArrayList<User>, так как мы ждём массив пользователей. Во втором методе обратите внимание на аннотацию Path, с помощью которой мы подменяем id в url на переданный при вызове метода getUser параметр. В третьем методе с помощью аннотации Body мы отмечаем, что объект User, переданный в параметре при вызове метода, будет телом запроса.

Далее перед отправкой запроса и получением результата нам нужно произвести инициализацию Retrofit’а и объекта интерфейса. Сделаем это в классе синглтоне, так как нам не нужно несколько объектов, выполняющих одну и ту же функцию.

public class Client {
   private static Client ourInstance = new Client();
   private static Api api;

   private static final String BASE_URL = "http://pentagon.api/";

   public static Client getInstance() {
       return ourInstance;
   }

   private Client() {
       OkHttpClient okHttpClient = new OkHttpClient.Builder()
               .addInterceptor(new HttpLoggingInterceptor().setLevel((BuildConfig.DEBUG) ? HttpLoggingInterceptor.Level.BODY : HttpLoggingInterceptor.Level.NONE))
               .build();

       Retrofit retrofit = new Retrofit.Builder()
       .baseUrl(BASE_URL)
       .client(okHttpClient)
       .addConverterFactory(GsonConverterFactory.create()).addCallAdapterFactory(RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io()))
       .build();

      
       api = retrofit.create(Api.class);
   }

   public Api getApi() {
       return api;
   }
}

В OkHttpClient мы добавили интерсептор — HttpLoggingInterceptor. При отправке запроса и получения ответа этот интерсептор будет логировать всю входящую и исходящую информацию. Это пригодится, если нам будет нужно посмотреть, что мы отправили в запросе или что нам пришло в ответ. Инициализируя объект retrofit, укажем наш базовый url, добавим GsonConverterFactory с помощью которой JSON-объекты преобразуются в JAVA-объекты и добавим RxJavaCallAdapterFactory, которая оборачивает возвращаемый в ходе выполнения запроса результат в Observable.

Теперь же перейдём непосредственно к отправке запросов и обработке результатов. Получим экземпляр нашего api интерфейса. Далее вызовем нужные методы, и так как результат приходит в виде Observable, подпишемся на них.

private Api api = Client.getInstance().getApi();
public void loadUsers() {
   api.getUserList()
       .observeOn(AndroidSchedulers.mainThread())
       .subscribe(users -> {
           view.saveUsers(users); 
       }, 
           //обработка ошибки
           Throwable::printStackTrace);
}
public void getUser(long id) {
   api.getUser(id)
           .observeOn(AndroidSchedulers.mainThread())
           .subscribe(user -> {
              view.saveUser(user);
           }, Throwable::printStackTrace);
}

public void saveUser(User user) {
   api.saveUser(user)
           .observeOn(AndroidSchedulers.mainThread())
           .subscribe(user1 -> {
               // User saved!
           }, Throwable::printStackTrace);
}

Осталось только вызвать написанные нами методы. Все запросы будут выполняться асинхронно, метод observeOn возвращает выполнение в указанный поток, в данном случае мы указываем главный, UI поток. Далее методом subscribe мы подписываемся на Observable, который нам возвращается и в скобках указываем действия, которые нужно произвести в случае успешного запроса и в случае ошибки. Не забываем отписываться от подписок!

Читать и комментировать
Почему я решил стать руководителем проектов
Поиск пути в Unity 3D

Максим Некрасов

23 мая 2016

Поиск пути в Unity 3D

Матрицы в Android, первая часть

Никита Марсюков

28 августа

Матрицы в Android, первая часть

Матрицы в Android, вторая часть

Никита Марсюков

31 августа

Матрицы в Android, вторая часть

Краснодар

Коммунаров, 268,
3 эт, офисы 705, 707

+7 (861) 200 27 34

Хьюстон

3523 Brinton trails Ln Katy

+1 833 933 0204

Москва

+7 (495) 145-01-05