美文网首页Android技术知识Android知识Android开发
retrofit 对callback错误的统一处理

retrofit 对callback错误的统一处理

作者: ZHG | 来源:发表于2017-07-12 22:38 被阅读2429次

    前言

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

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

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

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

    优化中——代码实现

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

    • 我们先创建一个抽象类 implements Callback<T>;
      public abstract class ZHGCallback<T> implements Callback<T> {}
    • 在 ZHGCallback 里面创建两个方法:一个抽象方法,一个 protect 方法
    public abstract void onSuccessful(Response<T> response);//方法一
    protected void onFail(final Call<T> call, Response<T> 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<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()){
                //解析后台返回的错误信息
                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<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);
        }
    }
    
    • 网络请求的实现:
      在请求的时候,我们直接使用我们定义的 ZHGCallback ,它会默认实现 onSuccessful 方法,onFail 方法在我们需要对错误单独处理时,重写就可以了。
    UserAPI.signin(entity, new ZHGCallback<LoginEntity>() {
                    @Override
                    public void onSuccessful(Response<LoginEntity> response) {
                        // 返回 200 ,请求成功,对数据进行处理
                    }
                    //⚠️如果对错误没有特殊处理,可以省略 onFail 方法;如果有特殊处理,重写 onFail 方法
                    @Override
                    protected void onFail(Call<T> call , Throwable t, Response<T> response) {
                        super.onFail(call, t, response);
                    }
                });
    

    总结

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

    相关文章

      网友评论

        本文标题:retrofit 对callback错误的统一处理

        本文链接:https://www.haomeiwen.com/subject/anuehxtx.html