Retrofit2のRxJavaCallアダプタを試す


## Retrofit2

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

[Simple HTTP with Retrofit 2 (Droidcon NYC 2015) by Jake Wharton](https://speakerdeck.com/jakewharton/simple-http-with-retrofit-2-droidcon-nyc-2015)

* 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](https://github.com/square/retrofit/blob/master/samples/src/main/java/com/example/retrofit/SimpleService.java)

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

## Callアダプタで実行

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

### インタフェースの定義

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

```Java
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を追加します。

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

### 同期実行

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

```Java
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メソッドを利用します。

```Java
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アダプタファクトリを追加しておきます。

```Java
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でラップします。

```Java
import rx.Observable;

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

### 実行

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

```Java
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 + ")");
  });

```