1. 程式人生 > >對OkHttpUtils中onError方法進行擴充套件列印更多資訊

對OkHttpUtils中onError方法進行擴充套件列印更多資訊

https://www.2cto.com/kf/201707/661662.html

最近開發Android專案用到了OkHttpUtils,專案中的伺服器是另一個同學搭的,能測試伺服器的介面的只有我了,比如400,500錯誤啊,都要我這邊列印才能找到出錯具體在哪個程式碼塊,但是,OkHttpUtils的錯誤資訊居然只有打印出響應碼,這真是讓人很無語啊。然後就花時間研究起背後的故事。

先附上OkHttpUtils的作者和用法:Android 一個改善的okHttp封裝庫

首先看一下普通返回的String型別的StringCallback

OkHttpUtils.get()
                .url(url)
                .build()
                .execute(new StringCallback() {
                    @Override
                    public void onError(Call call, Exception e, int id) {
                        e.printStackTrace();
                        Log.i(TAG, e.getMessage());
                    }
 
                    @Override
                    public void onResponse(String response, int id) {
                        Log.i(TAG, response);
                    }
                });

我們看到onError方法用了兩種方式列印,但是結果確是

這裡寫圖片描述

藍色部分是e.printStackTrace();
黑色部分是Log.i(TAG, e.getMessage());
我們發現確實只能列印響應碼。。。
那要如何輸出錯誤的網頁全部資訊呢,我們來看看基類Callback

public abstract class Callback<t>
{
    /**
     * UI Thread
     *
     * @param request
     */
    public void onBefore(Request request, int id)
    {
    }
 
    /**
     * UI Thread
     *
     * @param
     */
    public void onAfter(int id)
    {
    }
 
    /**
     * UI Thread
     *
     * @param progress
     */
    public void inProgress(float progress, long total , int id)
    {
 
    }
 
    /**
     * if you parse reponse code in parseNetworkResponse, you should make this method return true.
     *
     * @param response
     * @return
     */
    public boolean validateReponse(Response response, int id)
    {
        return response.isSuccessful();
    }
 
    /**
     * Thread Pool Thread
     *
     * @param response
     */
    public abstract T parseNetworkResponse(Response response, int id) throws Exception;
 
    public abstract void onError(Call call, Exception e, int id);
 
    public abstract void onResponse(T response, int id);
 
 
    public static Callback CALLBACK_DEFAULT = new Callback()
    {
 
        @Override
        public Object parseNetworkResponse(Response response, int id) throws Exception
        {
            return null;
        }
 
        @Override
        public void onError(Call call, Exception e, int id)
        {
 
        }
 
        @Override
        public void onResponse(Object response, int id)
        {
 
        }
    };
 
}

裡面有一個方法validateReponse(Response response, int id),上面的註釋if you parse reponse code in parseNetworkResponse, you should make this method return true.大概意思就是要解析資料就返回true吧,那我們就重寫這個方法,都返回true看會發生什麼

這裡寫圖片描述

好像列印了錯誤的網頁,但是仔細一看發現是onResponse中列印的,那表明onError方法就沒用了,導致所有事情都要在onResponse中處理了(雖然本來就是都在這裡處理的)。那有沒有方法讓錯誤的響應碼提交到onError中呢?我們再看Callback類的validateReponse方法,它返回的是response.isSuccessful();,我們繼續探索進去,發現如下程式碼

  public boolean isSuccessful() {
    return code >= 200 && code < 300;
  }

也就是說只有響應碼是200到300間的才會走onResponse方法(沒改之前),那都返回true要在哪裡處理呢。看回validateReponse的註釋,裡面出現了parseNetworkResponse這個方法,這個方法有引數Response,這個可以得到響應碼,然後還丟擲一個Exception,而onError方法中剛好有一個Exception的引數,於是有一個大膽的猜想,parseNetworkResponse丟擲的異常在onError中接收,所以重寫這個方法

@Override
    public String parseNetworkResponse(Response response, int id) throws Exception {
 
        if(response.code()>=200 && response.code()<300){
            return response.body().string();
        }else{
            throw new Exception("code is:"+response.code()+"\n"+response.body().string());
        }
 
    }

當響應碼為200到300時,我們返回響應體,其餘情況我們丟擲一個異常到onError中,結果如我們所想

這裡寫圖片描述

至此就完成了對OkHttpUtils中StringCallback中onError的擴充套件,附上自己重寫的MyStringCallback類

public abstract class MyStringCallback extends Callback<string> {
    @Override
    public boolean validateReponse(Response response, int id) {
        return true;
    }
 
    @Override
    public String parseNetworkResponse(Response response, int id) throws Exception {
 
        if(response.code()>=200 && response.code()<300){
            return response.body().string();
        }else{
            throw new Exception("code is:"+response.code()+"\n"+response.body().string());
        }
 
    }
 
}