RxJava2 + Retrofit2 完全指南 之 對返回Response的統一處理
前言
本章在上篇 統一狀態碼/Exception處理 的基礎上進行拓展,請現有一個必要的概念。
在介面對接中,我們最理想的狀態就是後端只返回一種資料結構,而且是規範的資料結構,但事實上大多數情況下都不會按照我們的理想狀態下返回的,比方說有資料的情況下,返回的是一種結構,無資料報錯又是另外一種資料結構,這就不可避免的需要我們對每個請求進行判斷,雖然可以通過和()(P)諧(Y)交(J)談(Y)來讓後端返回相同資料結構。但也存在另外一種情況:一個APP接入不同公司的API,這種情況就是無法避免的了。
對此,我們通過Retrofit可以在進行轉換之前進行統一的資料結構判斷和轉換,只將資料data返回,只關注資料結果就行。
實現
分析
為了模擬相關資料結構,我在原本的基礎上增加了兩種種不同的資料,然後通過隨機數獲取到其中的一個數據當做返回結果來操作,兩種資料格式如下:
- 資料格式 1
{ "code": 200, "data": { "id": "1", "name": "資料格式 1", "stargazers_count": 1 } }
- 資料格式 2
{ "status": 200, "msg": "請求成功", "userInfo": { "id": "2", "name": "資料格式 2", "stargazers_count": 2 } }
分析兩種資料, data
和 userInfo
中的欄位幾乎一致,當然現實基本上不會這樣的,這只是為了模擬一下這種情況,然後又是使用同一個實體類才這樣做。
編碼
先將上一個例子的三個類copy出來並重新命名。

CustConvert
對GsonResponseBodyConverter的convert方法進行修改,其實統一Resonse並沒有什麼難度,只是先一步將Resonse返回的資料使用原生的 JSONObject
先解析一遍,多加判斷,多加try而已,具體程式碼如下:
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> { private final TypeAdapter<T> adapter; /** * 模擬的假資料 */ private final List<String> mockResult; private final Random random; GsonResponseBodyConverter(TypeAdapter<T> adapter) { this.random = new Random(); this.adapter = adapter; mockResult = new ArrayList<>(); mockResult.add("{\"code\":200,\"message\":\"成功,但是沒有資料\",\"data\":[]}"); mockResult.add("{\"code\":-1,\"message\":\"這裡是介面返回的:錯誤的資訊,丟擲錯誤資訊提示!\",\"data\":[]}"); mockResult.add("{\"code\":401,\"message\":\"這裡是介面返回的:許可權不足,請重新登入!\",\"data\":[]}"); mockResult.add("{\"code\": 200,\"data\": {\"id\": \"1\",\"name\": \"資料格式 1\",\"stargazers_count\": 1}}"); mockResult.add("{\n\"status\": 200,\"msg\": \"請求成功\",\"userInfo\": {\"id\": \"2\",\"name\": \"資料格式 2\",\"stargazers_count\": 2}}"); } @Override public T convert(ResponseBody value) throws IOException { // 這裡就是對返回結果進行處理 // 其實我根本就沒使用真正返回的結果,都是用的自定義的結果 String jsonString = value.string(); try { // 這裡為了模擬不同的網路請求,所以採用了本地字串的格式然後進行隨機選擇判斷結果。 int resultIndex = random.nextInt(mockResult.size()); // 這裡模擬不同的資料結構 jsonString = mockResult.get(resultIndex); Log.e("TAG", "這裡進行了返回結果的判斷"); JSONObject jsonObject = new JSONObject(jsonString); try { // 如果這裡能取出資料,而且沒有問題,那就代表這是 code data msg 資料格式的 int code = jsonObject.getInt("code"); if (code != 200) { throw new NetErrorException(jsonObject.getString("message"), code); } try { return adapter.fromJson(jsonObject.getString("data")); } catch (Exception e) { throw new NetErrorException("資料解析異常", NetErrorException.PARSE_ERROR); } } catch (JSONException ignored) { } try { // 如果這裡能取出資料,而且沒有問題,那就代表這是 code data msg 資料格式的 int status = jsonObject.getInt("status"); if (status != 200) { throw new NetErrorException(jsonObject.getString("msg"), status); } return adapter.fromJson(jsonObject.getString("userInfo")); } catch (JSONException e) { throw new NetErrorException("資料解析異常", NetErrorException.PARSE_ERROR); } } catch (JSONException e) { e.printStackTrace(); throw new NetErrorException("資料解析異常", NetErrorException.PARSE_ERROR); } finally { value.close(); } } }
演示

MultipleResponse
結束
廣告
如果對你有幫助,請給我一個star,感激不盡。
如果有什麼錯誤,請儘量提出來,我會及時修改。