retrofit 对callback错误的统一处理

前言

在使用 retrofit 的时候,碰到这样一个问题,所有的网络接口都要进行网络请求错误判断而进行错误处理,也就是说每个 Callback 都要做同一件事情,这样就平白添加了许多无用的代码。以下是怎么对 retrofit 的 Callback 进行统一的错误处理

知识了解

retrofit 是对 okHttp 进行的封装,okHttp 请求返回的状态码为:

HTTP Status 说明
1xx 代表请求已被接受,需要继续处理 (临时相应)
2xx 代表请求已成功被服务器接收、理解、并接受
3xx 代表需要客户端采取进一步的操作才能完成请求
4xx 代表了客户端看起来可能发生了错误,妨碍了服务器的处理
5xx 表示服务器无法完成明显有效的请求

想要知道 HTTP Status 的具体说明请查看网址:HTTP 状态码-维基百科 ,该网址对 HTTP 状态码对每个大状态下各个小状态也进行了详细说明,能够更好的理解 HTTP 的状态码的意义。

优化前

使用过 Retrofit 的网友们,我们都知道,onResponse 方法一般是在网络请求后,有返回信息( HTTP 五类状态码 )时回调;而 onFailure 方法据我了解一般是由于请求延迟、超时,或者网络状态差等网络问题导致请求失败时回调。以下是我们刚接触retrofit时的写法:

UserAPI.signin(entity, new Callback() {
                @Override
                public void onResponse(Call< LoginEntity > call, Response< LoginEntity > response) {
                         if (response.isSuccessful()){
                           //1⃣️接口请求成功,对返回的数据进行处理
                        } else{
                          //2⃣️对后台返回的请求错误,进行处理
                        }
                }
                @Override
                public void onFailure(Call call, Throwable t) {
                    super.onFailure(call, t);
                    //3⃣️对当前网络情况差或者请求超时等网络请求延迟等一些错误处理。
                }
            });

以上看着没什么问题,但是 isSuccessful() 方法的 HTTP 状态码 是 200 到 300之间,在这之间都算是请求成功;并且在正常情况下只有 200 的时候后台才会返回数据,其他是没有数据的。因此我们还要在1⃣️处还要添加一些判断:

if (200 == response.code()) {
    //对后台返回的数据进行处理
} else {
    对后台返回200300之间的错误进行处理
}

而且每个接口都要对2⃣️和3⃣️处每个接口都要这么写,就额外添加了许多无用的重复代码,我们要怎么解决掉这个问题呢,让请求的方法更佳简介,相同的错误可以处理集中处理。以下是我在开发中使用的方法。

优化中——代码实现

使用retrofit异步请求都需要有个 Callback 回调,对请求结果进行处理,我们就重新封装下 Callback。
Callback 是一种 interface,我们不能 extends,也不能在 interface 里面实现功能,它只是一个接口或者说是一种监听。还好在 java 里面提供一个叫抽象类的概念( abstract 关键字修饰):

  • 我们先创建一个抽象类 implements Callback;
    public abstract class ZHGCallback implements Callback {}
  • 在 ZHGCallback 里面创建两个方法:一个抽象方法,一个 protect 方法
public abstract void onSuccessful(Response response);//方法一
protected void onFail(final Call call, Response response) {}//方法二

方法一是请求成功并且请求的 Code 是 200 的回调方法
方法二是统一的错误处理的方法,如果单个接口需要特别处理错误,请重写 onFail 方法
在实现的时候只需要写 onSuccessful(Response response) 方法就行了,如果想要对请求错误进行单独处理,可以重写 onFail() 方法:

  • 具体实现如下:
public abstract class ZHGCallback<T> implements Callback<T>{

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

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

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

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

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

    protected  void  onFail(Call call , Throwable t, Response 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()){
            //解析后台返回的错误信息
            ErrorEntity errorEntity = new ErrorEntity();
            try {
                errorEntity = ErrorEntity.parse(response.errorBody().string());
            } catch (IOException e) {
                Log.e(TAG, "ErrorEntity解析错误:" + e.getMessage());
            }
            String message;
            if (errorEntity.getErrorMessage() != null) {
                message = errorEntity.getErrorMessage();
            }else {
                message ="账号已过期,请重新登录";
            }
            // errorEntity.getErrorCode() 获取后台返回的 errorCode,根据 errorCode 前端做相应的处理
        }
    }
}

代码使用

我们以登录接口为例,一步一步实现网络请求。

  • 网络请求接口和方法的的定义
    定义一个类,按照 retrofit 的使用说明,定义请求方式及方法
public class UserAPI {
    private static final String API_URL = ApiConstant.Service_API + "users/";

    interface UserInterface {
// 登录
        @POST("signin")
        Call signIn(@Body SigninParameterEntity signinParameterEntity);
    }
// 使用用户名密码登录
    public static void signin(final SigninParameterEntity signinParameterEntity, final ZHGCallback callback) {
        Retrofit retrofit = RetrofitUtil.retrofitClient(API_URL);
        UserInterface userInterface = retrofit.create(UserInterface.class);
        userInterface.signIn(signinParameterEntity).enqueue(callback);
    }
}
  • 网络请求的实现:
    在请求的时候,我们直接使用我们定义的 ZHGCallback ,它会默认实现 onSuccessful 方法,onFail 方法在我们需要对错误单独处理时,重写就可以了。
UserAPI.signin(entity, new ZHGCallback() {
                @Override
                public void onSuccessful(Response response) {
                    // 返回 200 ,请求成功,对数据进行处理
                }
                //⚠️如果对错误没有特殊处理,可以省略 onFail 方法;如果有特殊处理,重写 onFail 方法
                @Override
                protected void onFail(Call call , Throwable t, Response response) {
                    super.onFail(call, t, response);
                }
            });

总结

对错误返回统一处理,大大的节省了代码量,并且可以很方便的修改错误信息,对网络请求管理更加便捷。现在大多数人都在使用 Rxjava+retrofit 进行网络请求,它逻辑清晰,代码实现起来更加方便,接下来,开始着手准备 Rx 的学习和整理。

你可能感兴趣的:(Android提升)