レトロフィットとRxJavaの統合

RetrofitとRxJavaの統合

1. 概要

この記事では、Retrofitを使用して単純なRxJava-readyRESTクライアントを実装する方法に焦点を当てます。

標準のRetrofitアプローチを使用して、GitHub APIと相互作用するサンプルアプリケーションを構築し、次にRxJavaを使用してそれを拡張して、リアクティブプログラミングの利点を活用します。

2. プレーンレトロフィット

まず、Retrofitを使用して例を作成しましょう。 GitHub APIを使用して、任意のリポジトリに100を超える投稿があるすべての投稿者の並べ替えられたリストを取得します。

2.1. Mavenの依存関係

Retrofitでプロジェクトを開始するには、次のMavenアーティファクトを含めましょう。


    com.squareup.retrofit2
    retrofit
    2.3.0



    com.squareup.retrofit2
    converter-gson
    2.3.0

最新バージョンについては、Maven Centralリポジトリのretrofitconverter-gsonを確認してください。

2.2. APIインターフェース

簡単なインターフェースを作成しましょう。

public interface GitHubBasicApi {

    @GET("users/{user}/repos")
    Call listRepos(@Path("user") String user);

    @GET("repos/{user}/{repo}/contributors")
    Call listRepoContributors(
      @Path("user") String user,
      @Path("repo") String repo);
}

listRepos()メソッドは、パスパラメーターとして渡された特定のユーザーのリポジトリーのリストを取得します。

listRepoContributers()メソッドは、特定のユーザーとリポジトリの寄稿者のリストを取得します。どちらもパスパラメーターとして渡されます。

2.3. 論理

RetrofitCallオブジェクトと通常のJavaコードを使用して、必要なロジックを実装しましょう。

class GitHubBasicService {

    private GitHubBasicApi gitHubApi;

    GitHubBasicService() {
        Retrofit retrofit = new Retrofit.Builder()
          .baseUrl("https://api.github.com/")
          .addConverterFactory(GsonConverterFactory.create())
          .build();

        gitHubApi = retrofit.create(GitHubBasicApi.class);
    }

    List getTopContributors(String userName) throws IOException {
        List repos = gitHubApi
          .listRepos(userName)
          .execute()
          .body();

        repos = repos != null ? repos : Collections.emptyList();

        return repos.stream()
          .flatMap(repo -> getContributors(userName, repo))
          .sorted((a, b) -> b.getContributions() - a.getContributions())
          .map(Contributor::getName)
          .distinct()
          .sorted()
          .collect(Collectors.toList());
    }

    private Stream getContributors(String userName, Repository repo) {
        List contributors = null;
        try {
            contributors = gitHubApi
              .listRepoContributors(userName, repo.getName())
              .execute()
              .body();
        } catch (IOException e) {
            e.printStackTrace();
        }

        contributors = contributors != null ? contributors : Collections.emptyList();

        return contributors.stream()
          .filter(c -> c.getContributions() > 100);
    }
}

3. RxJavaとの統合

Retrofitを使用すると、RetrofitCallアダプターを使用して、通常のCallオブジェクトの代わりにカスタムハンドラーを使用して呼び出し結果を受け取ることができます。 これにより、ここでRxJavaObservablesおよびFlowablesを使用できるようになります。

3.1. Mavenの依存関係

RxJavaアダプターを使用するには、このMavenアーティファクトを含める必要があります。


    com.squareup.retrofit2
    adapter-rxjava
    2.3.0

最新バージョンについては、Maven中央リポジトリのadapter-rxjavaを確認してください。

3.2. RxJavaコールアダプタを登録する

ビルダーにRxJavaCallAdapterを追加しましょう:

Retrofit retrofit = new Retrofit.Builder()
  .baseUrl("https://api.github.com/")
  .addConverterFactory(GsonConverterFactory.create())
  .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
  .build();

3.3. APIインターフェース

この時点で、インターフェイスメソッドの戻り値の型を変更して、Call<…>ではなくObservable<…>を使用することができます。 ObservableFlowableSingleMaybeCompletableなどの他のRxタイプを使用する場合があります。

Observableを使用するようにAPIインターフェースを変更しましょう。

public interface GitHubRxApi {

    @GET("users/{user}/repos")
    Observable> listRepos(@Path("user") String user);

    @GET("repos/{user}/{repo}/contributors")
    Observable> listRepoContributors(
      @Path("user") String user,
      @Path("repo") String repo);
}

3.4. 論理

RxJavaを使用して実装しましょう。

class GitHubRxService {

    private GitHubRxApi gitHubApi;

    GitHubRxService() {
        Retrofit retrofit = new Retrofit.Builder()
          .baseUrl("https://api.github.com/")
          .addConverterFactory(GsonConverterFactory.create())
          .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
          .build();

        gitHubApi = retrofit.create(GitHubRxApi.class);
    }

    Observable getTopContributors(String userName) {
        return gitHubApi.listRepos(userName)
          .flatMapIterable(x -> x)
          .flatMap(repo -> gitHubApi.listRepoContributors(userName, repo.getName()))
          .flatMapIterable(x -> x)
          .filter(c -> c.getContributions() > 100)
          .sorted((a, b) -> b.getContributions() - a.getContributions())
          .map(Contributor::getName)
          .distinct();
    }
}

4. 結論

RxJavaを使用する前後のコードを比較すると、次の方法で改善されていることがわかりました。

  • リアクティブ-データがストリームで流れるようになったため、ノンブロッキングバックプレッシャーで非同期ストリーム処理を実行できます

  • 明確–宣言的な性質のため

  • 簡潔–操作全体を1つの操作チェーンとして表すことができます

この記事のすべてのコードは利用可能ですover on GitHub.

パッケージcom.example.retrofit.basicには基本的な改造の例が含まれ、パッケージcom.example.retrofit.rxにはRxJava統合を使用した改造の例が含まれています。