retrofit 對(duì)callback錯(cuò)誤的統(tǒng)一處理

前言

在使用 retrofit 的時(shí)候,碰到這樣一個(gè)問(wèn)題,所有的網(wǎng)絡(luò)接口都要進(jìn)行網(wǎng)絡(luò)請(qǐng)求錯(cuò)誤判斷而進(jìn)行錯(cuò)誤處理,也就是說(shuō)每個(gè) Callback 都要做同一件事情,這樣就平白添加了許多無(wú)用的代碼。以下是怎么對(duì) retrofit 的 Callback 進(jìn)行統(tǒng)一的錯(cuò)誤處理

知識(shí)了解

retrofit 是對(duì) okHttp 進(jìn)行的封裝,okHttp 請(qǐng)求返回的狀態(tài)碼為:

HTTP Status 說(shuō)明
1xx 代表請(qǐng)求已被接受,需要繼續(xù)處理 (臨時(shí)相應(yīng))
2xx 代表請(qǐng)求已成功被服務(wù)器接收、理解、并接受
3xx 代表需要客戶端采取進(jìn)一步的操作才能完成請(qǐng)求
4xx 代表了客戶端看起來(lái)可能發(fā)生了錯(cuò)誤,妨礙了服務(wù)器的處理
5xx 表示服務(wù)器無(wú)法完成明顯有效的請(qǐng)求

想要知道 HTTP Status 的具體說(shuō)明請(qǐng)查看網(wǎng)址:HTTP 狀態(tài)碼-維基百科 ,該網(wǎng)址對(duì) HTTP 狀態(tài)碼對(duì)每個(gè)大狀態(tài)下各個(gè)小狀態(tài)也進(jìn)行了詳細(xì)說(shuō)明,能夠更好的理解 HTTP 的狀態(tài)碼的意義。

優(yōu)化前

使用過(guò) Retrofit 的網(wǎng)友們,我們都知道,onResponse 方法一般是在網(wǎng)絡(luò)請(qǐng)求后,有返回信息( HTTP 五類狀態(tài)碼 )時(shí)回調(diào);而 onFailure 方法據(jù)我了解一般是由于請(qǐng)求延遲、超時(shí),或者網(wǎng)絡(luò)狀態(tài)差等網(wǎng)絡(luò)問(wèn)題導(dǎo)致請(qǐng)求失敗時(shí)回調(diào)。以下是我們剛接觸retrofit時(shí)的寫法:

UserAPI.signin(entity, new Callback<LoginEntity>() {
                @Override
                public void onResponse(Call< LoginEntity > call, Response< LoginEntity > response) {
                         if (response.isSuccessful()){
                           //1??接口請(qǐng)求成功,對(duì)返回的數(shù)據(jù)進(jìn)行處理
                        } else{
                          //2??對(duì)后臺(tái)返回的請(qǐng)求錯(cuò)誤,進(jìn)行處理
                        }
                }
                @Override
                public void onFailure(Call<LoginEntity> call, Throwable t) {
                    super.onFailure(call, t);
                    //3??對(duì)當(dāng)前網(wǎng)絡(luò)情況差或者請(qǐng)求超時(shí)等網(wǎng)絡(luò)請(qǐng)求延遲等一些錯(cuò)誤處理。
                }
            });

以上看著沒(méi)什么問(wèn)題,但是 isSuccessful() 方法的 HTTP 狀態(tài)碼 是 200 到 300之間,在這之間都算是請(qǐng)求成功;并且在正常情況下只有 200 的時(shí)候后臺(tái)才會(huì)返回?cái)?shù)據(jù),其他是沒(méi)有數(shù)據(jù)的。因此我們還要在1??處還要添加一些判斷:

if (200 == response.code()) {
    //對(duì)后臺(tái)返回的數(shù)據(jù)進(jìn)行處理
} else {
    對(duì)后臺(tái)返回200~300之間的錯(cuò)誤進(jìn)行處理
}

而且每個(gè)接口都要對(duì)2??和3??處每個(gè)接口都要這么寫,就額外添加了許多無(wú)用的重復(fù)代碼,我們要怎么解決掉這個(gè)問(wèn)題呢,讓請(qǐng)求的方法更佳簡(jiǎn)介,相同的錯(cuò)誤可以處理集中處理。以下是我在開(kāi)發(fā)中使用的方法。

優(yōu)化中——代碼實(shí)現(xiàn)

使用retrofit異步請(qǐng)求都需要有個(gè) Callback 回調(diào),對(duì)請(qǐng)求結(jié)果進(jìn)行處理,我們就重新封裝下 Callback。
Callback 是一種 interface,我們不能 extends,也不能在 interface 里面實(shí)現(xiàn)功能,它只是一個(gè)接口或者說(shuō)是一種監(jiān)聽(tīng)。還好在 java 里面提供一個(gè)叫抽象類的概念( abstract 關(guān)鍵字修飾),

  • 我們先創(chuàng)建一個(gè)抽象類 implements Callback<T>;
    public abstract class ZHGCallback<T> implements Callback<T> {}
  • 在 ZHGCallback 里面創(chuàng)建兩個(gè)方法:一個(gè)抽象方法,一個(gè) protect 方法
public abstract void onSuccessful(Response<T> response);//方法一
protected void onFail(final Call<T> call, Response<T> response) {}//方法二

方法一是請(qǐng)求成功并且請(qǐng)求的 Code 是 200 的回調(diào)方法
方法二是統(tǒng)一的錯(cuò)誤處理的方法,如果單個(gè)接口需要特別處理錯(cuò)誤,請(qǐng)重寫 onFail 方法
在實(shí)現(xiàn)的時(shí)候只需要寫 onSuccessful(Response response) 方法就行了,如果想要對(duì)請(qǐng)求錯(cuò)誤進(jìn)行單獨(dú)處理,可以重寫 onFail() 方法;

  • 具體實(shí)現(xiàn)如下:
public abstract class ZHGCallback<T> implements Callback<T>{

    private String TAG = this.getClass().getSimpleName()+">>>>";

    @Override
    public void onResponse(Call<T> call, Response<T> response) {

        if (200 == response.code()){
            onSuccessful(call,response);
        }else {
            onFail(call,null,response);
        }
    }

    @Override
    public void onFailure(Call<T> call, Throwable t) {
        onFail(call,t,null);
    }

    public abstract void onSuccessful(Call<T> call, Response<T> response);

    protected  void  onFail(Call<T> call , Throwable t, Response<T> response){
        if (null == response){
            Toast.makeText(BaseApplication.getContext(),t.toString(),Toast.LENGTH_SHORT).show();
            return;
        }
        Log.e(TAG,"RESPONSE code is "+response.code()+": "+ response.raw().toString());
        if (null != response.errorBody()){
            //解析后臺(tái)返回的錯(cuò)誤信息
            ErrorEntity errorEntity = new ErrorEntity();
            try {
                errorEntity = ErrorEntity.parse(response.errorBody().string());
            } catch (IOException e) {
                Log.e(TAG, "ErrorEntity解析錯(cuò)誤:" + e.getMessage());
            }
            String message;
            if (errorEntity.getErrorMessage() != null) {
                message = errorEntity.getErrorMessage();
            }else {
                message ="賬號(hào)已過(guò)期,請(qǐng)重新登錄";
            }
            // errorEntity.getErrorCode() 獲取后臺(tái)返回的 errorCode,根據(jù) errorCode 前端做相應(yīng)的處理
        }
    }
}

代碼使用

我們以登錄接口為例,一步一步實(shí)現(xiàn)網(wǎng)絡(luò)請(qǐng)求。

  • 網(wǎng)絡(luò)請(qǐng)求接口和方法的的定義
    定義一個(gè)類,按照 retrofit 的使用說(shuō)明,定義請(qǐng)求方式及方法
public class UserAPI {
    private static final String API_URL = ApiConstant.Service_API + "users/";

    interface UserInterface {
// 登錄
        @POST("signin")
        Call<LoginEntity> signIn(@Body SigninParameterEntity signinParameterEntity);
    }
// 使用用戶名密碼登錄
    public static void signin(final SigninParameterEntity signinParameterEntity, final ZHGCallback<LoginEntity> callback) {
        Retrofit retrofit = RetrofitUtil.retrofitClient(API_URL);
        UserInterface userInterface = retrofit.create(UserInterface.class);
        userInterface.signIn(signinParameterEntity).enqueue(callback);
    }
}
  • 網(wǎng)絡(luò)請(qǐng)求的實(shí)現(xiàn):
    在請(qǐng)求的時(shí)候,我們直接使用我們定義的 ZHGCallback ,它會(huì)默認(rèn)實(shí)現(xiàn) onSuccessful 方法,onFail 方法在我們需要對(duì)錯(cuò)誤單獨(dú)處理時(shí),重寫就可以了。
UserAPI.signin(entity, new ZHGCallback<LoginEntity>() {
                @Override
                public void onSuccessful(Response<LoginEntity> response) {
                    // 返回 200 ,請(qǐng)求成功,對(duì)數(shù)據(jù)進(jìn)行處理
                }
                //??如果對(duì)錯(cuò)誤沒(méi)有特殊處理,可以省略 onFail 方法;如果有特殊處理,重寫 onFail 方法
                @Override
                protected void onFail(Call<T> call , Throwable t, Response<T> response) {
                    super.onFail(call, t, response);
                }
            });

總結(jié)

對(duì)錯(cuò)誤返回統(tǒng)一處理,大大的節(jié)省了代碼量,并且可以很方便的修改錯(cuò)誤信息,對(duì)網(wǎng)絡(luò)請(qǐng)求管理更加便捷。現(xiàn)在大多數(shù)人都在使用 Rxjava+retrofit 進(jìn)行網(wǎng)絡(luò)請(qǐng)求,它邏輯清晰,代碼實(shí)現(xiàn)起來(lái)更加方便,接下來(lái),開(kāi)始著手準(zhǔn)備 Rx 的學(xué)習(xí)和整理。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評(píng)論 19 139
  • 整體Retrofit內(nèi)容如下: 1、Retrofit解析1之前哨站——理解RESTful 2、Retrofit解析...
    隔壁老李頭閱讀 3,255評(píng)論 5 14
  • 前言RxJava和Retrofit也火了一段時(shí)間了,不過(guò)最近一直在學(xué)習(xí)ReactNative和Node相關(guān)的姿勢(shì),...
    AFinalStone閱讀 625評(píng)論 0 0
  • 開(kāi)始使用Retrofit 首先先聲明一個(gè)用于請(qǐng)求的接口 Converter.Factory factory = G...
    zyc_214閱讀 434評(píng)論 0 0
  • 適配器模式上一篇文章我們已經(jīng)分析了Retrofit解析注解封裝進(jìn)ServiceMethod的流程,讀者在這里要記住...
    andcoder閱讀 772評(píng)論 0 2

友情鏈接更多精彩內(nèi)容