1. 概述
本文重點介紹如何使用 RxJava 兼容的 REST 客户端,並使用 Retrofit 構建。
我們將構建一個與 GitHub API 交互的示例應用程序——採用標準的 Retrofit 方法,然後使用 RxJava 增強它,以利用 Reactive Programming 的優勢。
2. Plain Retrofit
首先,我們來構建一個使用 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>
有關最新版本,請查看 retrofit 和 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 允許我們使用自定義處理程序而不是正常的 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>
要獲取最新版本,請查看 adapter-rxjava 在 Maven 中心倉庫。
3.2. 註冊 RxJava Call 適配器
讓我們將 RxJavaCallAdapter 添加到構建器中:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
3.3. API 接口
此時,我們可以將接口方法返回類型更改為使用 Observable<…> 而不是 Call<…>。我們可以使用其他 Rx 類型,如 Observable、Flowable、Single、Maybe、Completable。
讓我們修改我們的 API 接口以使用 Observable:
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 之前和之後的代碼,我們發現它在以下方面得到了改進:
- 反應式 – 隨着我們的數據現在以流的形式流動,它使我們能夠進行非阻塞背壓的異步流處理
- 清晰 – 由於其聲明式特性
- 簡潔 – 整個操作可以表示為單個操作鏈
包 com.baeldung.retrofit.basic 包含基本的 Retrofit 示例,而包 com.baeldung.retrofit.rx 包含帶有 RxJava 集成的 Retrofit 示例。