Coding Story

在黑暗中寫故事 👻

0%

RxJava 特效:API 搭配 zip 的妙用

前言故事

小唯公司的門口角落,放有幾張小桌子,小唯正與另一位負責 API 介面開發的同事,在其中一張桌上討論要如何為既有 API 設計新的 API 接口。以小唯負責的手機 App 前端角色,當然是希望越簡單越好,一個畫面一支 API 是對 App 最簡單的方式,進入畫面時使用 API 更新資料、重整介面,但是 API 同事卻有其他考量,因為架構問題,他無法把每個功能畫面,都依照小唯的期待去設計介面。最後結果是有數個畫面,需要使用超過一支 API 去將資料整合起來。這對於原本就在使用 RxJava 的小唯團隊,腦中冒出一個之前看過的 operator - Zip

在沒有的 ReactiveX 之前

當一個畫面對應一支 API,流程是相當單純:


但是當一個畫面有需要兩支或以上 API 才能呈現內容,就「稍微」有點複雜了,有多種組合都可以達到目的,通常會視狀況使用。

相依性高的 API 組合

在有強烈相依性下的狀況,當一支 API 失敗,接下來的都會變成毫無意義,這時可以讓一支 API 接著另一支,當第一支結果回來後,先處理結果,再決定是否要執行第二支 API。這就有兩種可能的組合:



最重要的先顯示

當第二支 API 只是單純的附加資訊時,這時使用者先看到第一支 API 資訊比較重要,就可以使用以下變形。這讓第一支結果回來後,就立刻渲染,等第二支 API 回來,再渲染第二支結果,即使後面的 API 失敗,對使用者的影響也較小:



大家都重要,且無相依性

當 API 誰先誰後的順序不重要,而且沒有相依性時,線性同步發送且等待結果都回來後,再渲染畫面:



非同步進行

非同步進行也是常用的方式之一,如果 API 無相依性,或者資料順序不重要,也可以非同步發送 API,哪個先回來就先渲染哪個。缺點也是常常會看到畫面先長出一部分,接著馬上在跳出剩下的部分,至於哪部分先,哪個後出來,則無法預測:


當資料內容必須一同顯示,那就得等待結果都回來後才渲染,這是小唯公司內常見的用法,優點是不會看到畫面分別跳出來,缺點是不太容易實作,常常看到有寫錯亂的狀況(不會用又愛用,為什麼不乾脆使用同步方式,一個接一個):


ReactiveX 的出現

自從小唯團隊使用 RxJava zip 後,之前不容易實作的非同步寫法,突然變成無難度,zip 的特性是將多個資料來源,只在所有來源都接收到資料後,才一起發通知處理。下方的圖可以看成,白圈是 API 一號回傳的結果,黃色倒三角是 API 二號回傳的結果,黃色圈則是兩個 API 合併後的結果,也就預期達成的效果:


使用 zip 後流程變成如下:


程式碼寫起來出奇的簡單:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public Single<Result> getScreenData() {
// 非同步呼叫 API 1
Single<ApiResult> api_1_result = api1();

// 非同步呼叫 API 2
Single<ApiResult> api_2_result = api2();

// 等待兩個結果都回來後,使用 handleApiResult 將資料轉換成 UI 可使用的 data model
return Single.zip(api_1_result, api_2_result, this::handleApiResult);
}

private Result handleApiResult(
ApiResult api_1_result,
ApiResult api_2_result) {
Result result = new Result();
// 模擬將資料整合
result.setData1(api_1_result);
result.setData2(api_2_result);
return result;
}


------------- 本文结束 好想精通 RxJava 啊~ -------------