1概要

この記事では、http://square.github.io/retrofit/[Retrofit]を使って簡単なhttps://github.com/ReactiveX/RxJava[RxJava-ready]RESTクライアントを実装する方法に焦点を当てます。

標準のRetrofitアプローチを使用してGitHub APIと対話するサンプルアプリケーションを作成し、次にRxJavaを使用してそれを強化してReactive Programmingの利点を活用します。


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

最初にRetrofitを使って例を作りましょう。 GitHub APIを使用して、任意のリポジトリに100を超える貢献がある貢献者すべてのソートリストを取得します。


2.1. Mavenの依存関係

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

<dependency>
    <groupId>com.squareup.retrofit2</groupId>
    <artifactId>retrofit</artifactId>
    <version>2.3.0</version>
</dependency>

<dependency>
    <groupId>com.squareup.retrofit2</groupId>
    <artifactId>converter-gson</artifactId>
    <version>2.3.0</version>
</dependency>

最新版については、https://search.maven.org/classic/#search%7C1%7Cg%3A%22com.squareup.retrofit2%22%20AND%20a%3A%22retrofit%22[をご覧ください。後付け]およびhttps://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22com.squareup.retrofit2%22%20AND%20a%3A%22converter-gson%22[converter-gson]Maven Centralリポジトリで。


2.2. APIインターフェース

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

public interface GitHubBasicApi {

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

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


listRepos()

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


listRepoContributers()

メソッドは、指定されたユーザーとリポジトリの貢献者のリストを取得します。両方ともパスパラメータとして渡されます。


2.3. 論理

Retrofit

Call

オブジェクトと通常の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<String> getTopContributors(String userName) throws IOException {
        List<Repository> 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<Contributor> getContributors(String userName, Repository repo) {
        List<Contributor> 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は、Retrofit

Call

アダプタを使用して、通常の

Call

オブジェクトではなくカスタムハンドラを使用して呼び出し結果を受け取ることができます。これはここでRxJava

Observables



Flowables

を使うことを可能にします。


3.1. Mavenの依存関係

RxJavaアダプターを使用するには、このMaven成果物を含める必要があります。

<dependency>
    <groupId>com.squareup.retrofit2</groupId>
    <artifactId>adapter-rxjava</artifactId>
    <version>2.3.0</version>
</dependency>

最新版はhttps://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22com.squareup.retrofit2%22%20AND%20a%3A%22adapter-rxjava%22[adapter Maven中央リポジトリの-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 <…​>

を使用するようにインターフェイスメソッドの戻り型を変更できます。

Observable



Flowable



Single



Maybe



Completable

などの他のRxタイプを使用することもできます。


Observable

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

public interface GitHubRxApi {

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

    @GET("repos/{user}/{repo}/contributors")
    Observable<List<Contributer>> 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<String> 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つの操作として表すことができます。

この記事のすべてのコードはhttps://github.com/eugenp/tutorials/tree/master/libraries[GitHubで利用できます。]

パッケージ

com.baeldung.retrofit.basic

に基本的なレトロフィットの例が含まれ、パッケージ


_com.baeldung.retrofit .

_

rxにRxJava統合のレトロフィットの例が含まれています。