1. 概述
本文重點介紹瞭如何使用 RxJava 兼容 的 REST 客户端,並利用 Retrofit。
我們將構建一個與 GitHub API 交互的示例應用程序——採用標準的 Retrofit 方法,然後通過使用 RxJava 來增強它,從而利用 Reactive Programming 的優勢。
2. 使用 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 中央倉庫。
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>要查看最新版本,請查閲 adapter-rxjava 在 Maven 中央倉庫。
3.2. 註冊 RxJava 調用適配器
讓我們將 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 示例。