1. 概述

本文将带你实现一个支持RxJava的REST客户端,使用Retrofit框架。我们将通过GitHub API实战演示:先用传统Retrofit方式实现,再用RxJava进行响应式编程增强。

2. 基础Retrofit实现

先构建一个纯Retrofit的示例:获取任意仓库中贡献超过100次的贡献者排序列表。

2.1 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>

✅ 最新版本请查阅Maven中央仓库:retrofitconverter-gson

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(): 获取指定用户的所有仓库列表
  • listRepoContributors(): 获取指定仓库的贡献者列表

2.3 业务逻辑实现

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的Call Adapter机制,我们可以用RxJava的Observable替换默认的Call对象。

3.1 Maven依赖

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

✅ 最新版本请查阅:adapter-rxjava

3.2 注册RxJava适配器

在Retrofit构建器中添加RxJavaCallAdapter

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

3.3 API接口改造

将返回类型从Call<...>改为Observable<...>,支持多种RxJava类型:

public interface GitHubRxApi {

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

📌 可选类型:Observable, Flowable, Single, Maybe, Completable

3.4 响应式业务逻辑

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. 响应式能力
    数据以流的形式传输,支持异步非阻塞处理和背压控制

  2. 代码清晰度
    声明式编程让业务逻辑一目了然,告别回调地狱

  3. 代码简洁性
    整个操作链一气呵成,减少50%+的样板代码

💻 完整代码请参考:GitHub仓库
基础实现路径:com.baeldung.retrofit.basic
RxJava集成路径:com.baeldung.retrofit.rx


原始标题:Integrating Retrofit with RxJava