Help us understand the problem. What is going on with this article?

Retrofit2のRxJavaCallアダプタを試す

More than 5 years have passed since last update.

Retrofit2

現時点では2.0.0-beta1が最新です。
Callアダプタというものが追加されています。以下のような特徴があるようです。
これ以外にDynamic URL,Dynamic Query Paramも便利そうです。

Simple HTTP with Retrofit 2 (Droidcon NYC 2015) by Jake Wharton

  • Call encapsulates single request/response interaction
  • Models a single request/response pair
  • Separates request creation from response handling
  • Each instance can only be used once..
  • ...instances can be cloned
  • Supports both synchronous and asynchronous execution.
  • can be (actually) canceled

GitHubのリポジトリにあるサンプルコードを参考にRxJavaCallアダプタの使い方を試してみました。

SimpleService.java

サンプルにはObservableを利用する方法が書かれていなかったので、Jake Wharton氏のスライドを参考に修正しました。

Callアダプタで実行

まずはサンプルコードのままで実行してみました。非同期での実行も試してみます。

インタフェースの定義

サンプルではデフォルトのCallでラップされています。

import retrofit.Call;

public interface GitHub {
  @GET("/repos/{owner}/{repo}/contributors")
  Call<List<Contributor>> contributors(
    @Path("owner") String owner,
    @Path("repo") String repo);
}

Retrofitを生成

ビルダでRetrofitインスタンスを生成します。
コンバータファクトリはGsonConverterFactoryを追加します。

Retrofit retrofit = new Retrofit.Builder()
  .baseUrl(API_URL)
  .addConverterFactory(GsonConverterFactory.create())
  .build();

同期実行

サンプルでは同期実行しています。

GitHub github = retrofit.create(GitHub.class);
Call<List<Contributor>> call = github.contributors("square", "retrofit");

List<Contributor> contributors = call.execute().body();
for (Contributor contributor : contributors) {
  Log.d(TAG, contributor.login + " (" + contributor.contributions + ")");
}

非同期実行

非同期で実行する場合は、enqueueメソッドを利用します。

GitHub github = retrofit.create(GitHub.class);
Call<List<Contributor>> call = github.contributors("square", "retrofit");

call.enqueue(new Callback<List<Contributor>>() {
  @Override
  public void onResponse(Response<List<Contributor>> response) {
    for (Contributor contributor : response.body()) {
      Log.d(TAG, contributor.login + " (" + contributor.contributions + ")");
    }
  }

  @Override
  public void onFailure(Throwable t) {

  }
});

RxJavaで実行

ライブラリ

以下のライブラリを使用しています。adapter-rxjavaが必要です。

dependencies {
  compile 'io.reactivex:rxjava:1.0.14'
  compile 'com.squareup.okhttp:okhttp:2.5.0'
  compile 'com.squareup.retrofit:retrofit:2.0.0-beta1'
  compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta1'
  compile 'com.squareup.retrofit:converter-gson:2.0.0-beta1'
}

アダプタの設定

ビルダでRxJavaCallアダプタファクトリを追加しておきます。

Retrofit retrofit = new Retrofit.Builder()
  .baseUrl(API_URL)
  .addConverterFactory(GsonConverterFactory.create())
  .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
  .build();

これがないと実行時に以下のようなエラーが発生します。

Unable to create call adapter for rx.Observable<java.util.List<Contributor>>

インタフェース

CallではなくObservableでラップします。

import rx.Observable;

public interface GitHub {
  @GET("/repos/{owner}/{repo}/contributors")
  Observable<List<Contributor>> contributors(
    @Path("owner") String owner,
    @Path("repo") String repo);
}

実行

flatMapしてから一件づつ表示してみました。

GitHub github = retrofit.create(GitHub.class);
Observable<List<Contributor>> observable = github.contributors("square", "retrofit");

observable
  .flatMap(contributors -> {
    return Observable.from(contributors);
  })
  .subscribe(contributor -> {
    Log.d(TAG, contributor.login + " (" + contributor.contributions + ")");
  });

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away