1. 程式人生 > >Retrofit響應資料及異常處理策略

Retrofit響應資料及異常處理策略

今天我們來談談客戶端對通訊協議的處理,主要分為三部分:約定響應資料格式,響應資料的自動對映以及錯誤處理三部分。由於資料協議採用json的居多,因此我們在此基礎上進行說明。

約定響應資料格式

協議格式

通常來說,你拿到的設計文件中會存在通訊協議的說明,對於客戶端來說,一個良好的通訊協議需要能描述操作狀態(操作碼+操作提示)以操作結果,因此,常見的響應資料的格式如下:

{
  "code": 0,
  "msg": "正常",
  "data": {
    "id": 1,
    "account": "121313",
    "accountName": "alipay"
, "income": "600.000000" }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

code定義

code為我們自定義的操作狀態碼,首先來看我們常用的定義:

code 說明
0 操作成功的訊息提示
1 客戶端認證失敗,一般是客戶端被惡意修改
2 使用者認證失敗
3 提交引數錯誤:引數缺失、引數名不對等
4 提交引數校驗失敗,一般是提交給服務端的資料格式有誤,多發生在表單提交的場景中
5 自定義錯誤,服務端發生不可恢復的錯誤等

msg定義

msg為伺服器端返回的操作資訊。 
無論操作成功與否,客戶端都應該根據業務給出準確的提示,客戶端則根據實際情況選擇展示與否。

data 定義

data則是請求返回的具體內容,通常data根據請求介面的不同最終會被解析成不同的實體類。

示例

下面我們以獲取訊息列表和訊息詳情兩個介面返回的響應資料作為示例: 
訊息列表:

{
    "code": 0,
    "data": {
        "list": [
            {
                "content": "你參加的活動已經開始了...",
                "createtime
": "2016-09-23 16:44:02", "id": "4480", "status": 0, "title": "活動開始", "type": "1" }, { "content": "你參加的活動已經結束...", "createtime": "2016-09-19 14:30:02", "id": "4444", "status": 0, "title": "活動結束", "type": "1" } ]
, "total": 2 }
, "msg": "正常" }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

訊息詳情

{
    "code": 0,
    "data": {
        "detail":
            {
                "content": "你參加的活動已經開始了,請準時到你的活動中去執行",
                "createtime": "2016-09-23 16:44:02",
                "id": "4480",
                "status": 0,
                "title": "活動開始",
                "type": "1"
            },

    },
    "msg": "正常"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

響應資料對映實體資料模型

當我們接受到如上格式的響應資料時,下面便是考慮如何應用的問題,也就是如何將協議轉換?是在獲取響應的時候自動轉換還是手動轉換?轉換成Java實體類還是String?

“偷懶”是程式設計師的天性,我們當然不希望花費時間在這種無創造性的工作上,所以我們考慮在收到響應的時候直接將其轉換為java實體類。

確定了我們的目標之後,接下來,首要任務是對資料協議進行抽象?什麼叫做資料協議抽象? 
所謂的資料協議抽象就是根據聚合性,通用性,隔離性三原則將整個資料協議進行切分複用,以便更好的對映成我們需要的資料模型。

我們對剛才約定的資料協議格式進行協議抽象後,可以拿到類似以下的實體模型:

public class Result<T> {
    private int code;
    private String msg;
    private T data;

    //...set和get方法
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

Result做為所有響應模型的公共基類,其中的code,msg,data分別用來對映我們通訊協議。其中,泛型化的data確保接受不同的實體模型,可以看出,我們通過資料協議抽象之後,最終得到了一個良好的資料模型。

為了下面的需要我們一同將訊息列表和訊息詳情的實體類放上來:

public class message{

    private String content;
    private String createtime;
    private String id;
    private int status;
    private String title;
    private String type;

    //...set和get方法
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
public class messageList {
    private int total;
    private List<Message> list;

    //...set和get方法

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

現在來看看我們理想的獲取訊息列表和獲取訊息詳情的介面應該是什麼樣的:

@GET("/user/message/list")
Call<Result<MessageList>> getMessageList(@Query("page") int page);

@GET("/user/message")
Call<Result<Message>> getMessage(@Query("mid") int mid);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

結合我們上面所述,我們希望每個api最後返回給我們的都是Result

provided 'com.google.code.gson:gson:2.7'
  • 1
  • 1

接下來是新增Converter依賴:

com.squareup.retrofit2:converter-gson
  • 1
  • 1

最後為retrofit設定Converter:

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

GitHubService service = retrofit.create(GitHubService.class);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

這樣,我們的請求和響應由Gson進行處理:請求體(使用@Body)被對映成json,響應體被對映成實體資料模型。

上面我們談到了通訊協議格式以及如何利用retrofit的Converter實現協議和實體之間的自動對映。此時我們呼叫任何服務介面其使用大體如下,以獲取訊息列表介面為例:

   Call<Result<MessageList>> call = ApiFactory.getUserApi().getMessageList(mCurrentPage * getPageSize(), getPageSize());
        call.enqueue(new Callback<Result<MessageList>>() {
            @Override
            public void onResponse(Call<Result<MessageList>> call, Response<Result<MessageList>> response) {
                Result<MessageList> result = response.body();
                if (result.isOk()) {//操作正確

                } else {//操作失敗
                    switch (result.getCode()) {
                        case 1:

                            break;
                        case 2:

                            break;
                        case 3:
                            break;
                        case 4:
                            break;
                        case 5:

                            break;
                    }
                }
            }

            @Override
            public void onFailure(Call<Result<MessageList>> call, Throwable t) {
                //響應失敗
            }
        });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

錯誤處理

引入RxJava之前哪點事

按道理說,retrofit講到這裡已經足夠了,在此基礎上在進行二次封裝形成自己的框架也很不錯。但是由於RxJava發展確實不錯,因此retrofit引入對rxjava的支援,二者的有效結合才能發揮更強大的力量。

不瞭解RxJava同學可以就此打住或者先去了解相關資料。rxjava並無多大難度,明白理論之後再加上多練即可。對rxjava實現感興趣的童鞋可以參看去年寫的教你寫響應式框架

再來說說,在新專案開始的時候,我為什麼選擇引入rxjava,不引入不行麼? 
我並未考慮引入rxjava的原因我只想使用retrofit這個網路請求庫代替原有的async-http-client,後面發現引入rxjava能夠非常容易的幫助我們進行執行緒切換以及合理的處理網路異常。

如何引入rxjava?

引入rxjava非常簡單,需要新增以下依賴:

 compile 'io.reactivex:rxjava:1.1.0'
 compile 'io.reactivex:rxandroid:1.1.0'
  • 1
  • 2
  • 1
  • 2

接下來還需要引入adapter來將retrofit中Call轉換為rxjava中的Observable:

compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2'
  • 1
  • 1

最後需要在程式碼中啟用該adapter:

Retrofit.Builder  mBuilder = new
Retrofit.Builder().addCallAdapterFactory(RxJavaCallAdapterFactory.create())

    相關推薦

    Retrofit響應資料異常處理策略

    今天我們來談談客戶端對通訊協議的處理,主要分為三部分:約定響應資料格式,響應資料的自動對映以及錯誤處理三部分。由於資料協議採用json的居多,因此我們在此基礎上進行說明。 約定響應資料格式 協議格式 通常來說,你拿到的設計文件中會存在通訊協議的說明,

    Python抽象異常處理

    訪問 崩潰 span peer test all 機制 出現 import #面向對象:多態、封裝、繼承#1 多態:意味著即使不知道變量所引用的對象類型是什麽,還是能對他進行操作,而且也會根據他的不同類型表現出不同的行為#多態和方法from random import ch

    zuul網關Filter處理流程異常處理

    println 沒有 actor stat blog 一個地方 cli ram color 本文轉載自:https://blog.csdn.net/tianyaleixiaowu/article/details/77893822 上一篇介紹了java網關Zuul的簡單使用

    Spring-Batch學習總結(1)——重要概念,環境搭建,名詞解釋,第一個項目異常處理

    img truct 設定 uil sna sta col key services Spring-batch框架學習總結(1)一.初識Spring-batch框架:1.核心名詞解釋:Job:是Spring-batch框架的核心概念,它包含了批處理的所有操作Step:每一個J

    【Java筆記】IO流中檔案複製異常處理

    import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class Main

    python入門19 異常異常處理 異常捕獲

      常見異常舉例 """ 一些異常舉例:""" '''模組不存在 ModuleNotFoundError: No module named 'data' ''' #import data1 '''索引越界 IndexError: list index out of range ''' l

    WebAPI介面設計:SwaggerUI文件 / 統一響應格式 / 統一異常處理 / 統一許可權驗證

    為什麼還要寫這類文章?因為我看過網上很多講解的都不夠全面,而本文結合實際工作講解了swaggerui文件,統一響應格式,異常處理,許可權驗證等常用模組,並提供一套完善的案例原始碼,在實際工作中可直接參考使用。 一、先看看最終效果 這是最後生成的swagerui文件,大家可以直接訪問這個地址體驗: htt

    Java異常異常處理

    Java異常簡介 Java異常是Java提供的一種識別及響應錯誤的一致性機制。Java異常機制可以使程式中異常處理程式碼和正常業務程式碼分離,保證程式程式碼更加優雅,並提高程式健壯性。按照程式碼的預先設定的異常處理邏輯,針對性地處理異常,讓程式盡最大可能恢復正常並繼續執行,且保持程式碼的清晰。J

    POI-excel匯入資料錯誤異常處理-Unexpected element: CDATA

    org.apache.poi.POIXMLException: org.apache.xmlbeans.XmlException: error: Unexpected element: CDATA at org.apache.poi.xssf.usermodel.XSSFSheet.read(X

    13-面向物件異常處理

    面向物件及異常處理 內建函式 總結:__init__、__del__、__str__、attr系列、item系列、__call__ __str__與__repr__ 使用print/str方法時會自動觸發__str__方法,當__str__不存在,嘗試__repr__ 使用repr方法時會自動觸發_

    ARM的暫存器異常處理機制

    arm的暫存器:     普通:r0-r15         r0-r12   //儲存任何資料         r13(sp)  

    【mysql+java】捕獲資料庫中未查到資料進行異常處理

    文章目錄前言準備工作 思路分析流程圖分析程式碼分析說明 捕獲資料庫未查到資料異常處理 前言         當用戶查資料庫中的表單以此驗證表單中是否和即將要插入的資料重複,捕獲重複的資料以此來統計重複資

    異常層次結構異常處理(try、catch、finally)

    在Java程式語言設計中,所有的異常都是由類來表示,異常物件都是派生於Throwable類的一個例項。下面是Java異常層析結構的一個簡單示意圖: 由圖可知,所有異常類都直接或間接的繼承於Throwable類。 具體分類: Java把所有非正常情況分為Error(錯

    【C#】氣泡排序、隱式和顯式轉換、函式異常處理

    一、普通氣泡排序: C#中常見的排序方法有:氣泡排序,快速排序,插入排序,選擇排序、堆排序以及歸併排序。雖然還沒學習過,但是也有耳聞,就先把它們先歸類。今天主要講這裡面最常見的氣泡排序。 【概念】 氣泡排序也就是講一組需要排序的數,進行從小到大,或從大到小的排列。計算機

    Java學習筆記05--強制型別轉換 ;內部類(瞭解即可) ;Java異常體系異常處理;iOS中的try catch 塊

    ===============java相關講解============= 強制型別轉換: 基本資料型別的轉換 小資料型別---->大的資料型別 自動型別轉換 大資料型別----->小資料型別 強制型別轉換

    JavaEE開發之SpringMVC中的自定義攔截器異常處理

    上篇部落格我們聊了《》,本篇部落格我們就聊一下自定義攔截器的實現、以及使用ModelAndView物件將Controller的值載入到JSTL上、最後再聊一下異常的捕獲處理。這些在日常開發中都是經常使用的東西。具體請看下方內容。 一、自定義攔截器 顧名思義,攔截器是負責攔截某些東西的工具。本部分我們建立的攔

    pyrhon類約束異常處理和日誌模塊

    Coding 依賴 div 寫入內容 記錄 添加 文件的 col 發的 類的約束 class Base: #對子類進行了約束,必須重寫該方法 def login(self): print(‘方法錯誤,必須用定義login方法‘)

    oracle觸發器例項異常處理

    1.寫觸發器的業務需求:     我需要在工單表(up_ask)插入資料或更新資料時通過觸發器(currentnew_ask_trigger)將工單表的資料插入到一箇中間表(nosc_reportnew)中 2.出現的問題:     如果工單表的資料超過了中間表字段資料長度

    3. ARMv8 中斷異常處理(包括系統呼叫,系統呼叫即同步異常

    ARMv8 64bits相對於之前的 32bits 有較大變動,所有中斷及異常的處理總入口都在entry.S 原始檔中。 1.1.       異常介紹(中斷即稱為 非同步異常) 分為同步和非同步 兩種型別異常,中斷劃入非同步異常型別: Synchronous(同步異常)

    Java異常機制異常處理建議

    1、Java異常機制        異常指不期而至的各種狀況,如:檔案找不到、網路連線失敗、非法引數等。異常是一個事件,它發生在程式執行期間,干擾了正常的指令流程。Java通過API中Throwable類的眾多子