关于Retrofit返回错误信息的统一解决办法

来源:互联网 发布:大数据的前沿技术培训 编辑:程序博客网 时间:2024/05/16 14:32

最近哥们儿遇到的一个棘手难题,关于Retrofit请求的处理,一开始我觉得这种一般简单,根据返回code来就行,框架都给封装好了啊,之后自己上手之后才发现有些还是需要处理的。

问题如下图所示:

我来解释一下,Call里面的泛型和返回的对应不上,但是还是会走成功,同时response.isSuccess()为tue,对象里面的属性全是null(很好理解,因为JavaBean根本对应不上啊),奇怪的是Gson并没有抛错,郁闷,所以我们就只能手动处理这些异常了!
首先特别感谢博主的文章Retrofit统一处理服务器返回参数,这篇文章已经非常完整详细地讲解了Retrofit的相关处理办法,只是苦于木有Demo,我这边自己写Demo的时候还遇到了一个坑,就是没有办法收到异常,最终发现原来是Exception继承的问题,我一开始继承了Exception,后来才发现RunTimeException才可以中断之后的操作,所以修改如下。

package com.marsjiang.myretrofiterrortest.expection;/** * Created by Jiang on 2017-09-28. */public class MyException extends RuntimeException  {    public MyException(){        super();    }    public MyException(String msg){        super(msg);    }}
返回消息类和原博主保持一致:

package com.marsjiang.myretrofiterrortest.bean;/** * Created by Jiang on 2017-09-28. */public class Result<T> {    private int state;    private String msg;    private T data;    public int getState() {        return state;    }    public void setState(int state) {        this.state = state;    }    public String getMsg() {        return msg;    }    public void setMsg(String msg) {        this.msg = msg;    }    public T getData() {        return data;    }    public void setData(T data) {        this.data = data;    }}


下面来介绍其他的主要类(具体的讲解大家可以参考上篇博主的文章,写的非常棒,我就不啰嗦了):

MyGsonConverterFactory

package com.marsjiang.myretrofiterrortest.myretrofit;import com.google.gson.Gson;import com.google.gson.TypeAdapter;import com.google.gson.reflect.TypeToken;import java.lang.annotation.Annotation;import java.lang.reflect.Type;import okhttp3.RequestBody;import okhttp3.ResponseBody;import retrofit2.Converter;import retrofit2.Retrofit;/** * Created by Jiang on 2017-09-28. */public final class MyGsonConverterFactory extends Converter.Factory {    /**     * Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and     * decoding from JSON (when no charset is specified by a header) will use UTF-8.     */    public static MyGsonConverterFactory create() {        return create(new Gson());    }    /**     * Create an instance using {@code gson} for conversion. Encoding to JSON and     * decoding from JSON (when no charset is specified by a header) will use UTF-8.     */    public static MyGsonConverterFactory create(Gson gson) {        return new MyGsonConverterFactory(gson);    }    private final Gson gson;    private MyGsonConverterFactory(Gson gson) {        if (gson == null) throw new NullPointerException("gson == null");        this.gson = gson;    }    @Override    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,                                                            Retrofit retrofit) {        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));        return new MyGsonResponseBodyConverter<>(gson, adapter);    }    @Override    public Converter<?, RequestBody> requestBodyConverter(Type type,                                                          Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));        return (Converter<?, RequestBody>) new MyGsonResponseBodyConverter<>(gson, adapter);    }}

MyGsonResponseBodyConverter:

package com.marsjiang.myretrofiterrortest.myretrofit;import com.google.gson.Gson;import com.google.gson.TypeAdapter;import com.google.gson.stream.JsonReader;import com.marsjiang.myretrofiterrortest.bean.Result;import com.marsjiang.myretrofiterrortest.expection.MyException;import java.io.IOException;import java.io.StringReader;import okhttp3.ResponseBody;import retrofit2.Converter;/** * Created by Jiang on 2017-09-28. */final class MyGsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {    private final Gson gson;    private final TypeAdapter<T> adapter;    private static final int FAILURE = 0;       // 失败 提示失败msg    private static final int SUCCESS = 1;       // 成功    private static final int TOKEN_EXPIRE = 2;  // token过期    private static final int SERVER_EXCEPTION = 3;  // 服务器异常    MyGsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {        this.gson = gson;        this.adapter = adapter;    }    @Override    public T convert(ResponseBody value) throws IOException {        JsonReader jsonReader = gson.newJsonReader(value.charStream());        String json = value.string();        try {            verify(json);//            return adapter.read(jsonReader);            return adapter.read(gson.newJsonReader(new StringReader(json)));        } finally {            value.close();        }    }    private void verify(String json) {        Result result = gson.fromJson(json, Result.class);        if (result.getState() != SUCCESS) {            int a = result.getState();            switch (result.getState()) {                case SERVER_EXCEPTION:                    throw new MyException(result.getMsg());                case TOKEN_EXPIRE:                    throw new MyException(result.getMsg());                default://                    throw new MyException("不清楚什么原因!");            }        }    }}

这样抛出来的异常就可以被retrofit的onFailure()方法接收到了!关于异常的code大家自己去和服务端定好就行!微笑


在MainActivity中,我添加了一个okhttp过滤器,旨在监听每个请求,并将其打印出来,前提是大家需要导入一个第三方:


compile 'com.squareup.okhttp3:logging-interceptor:3.1.2'

下面是完整代码:

package com.marsjiang.myretrofiterrortest;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.util.Log;import com.marsjiang.myretrofiterrortest.bean.Result;import com.marsjiang.myretrofiterrortest.bean.UserReturnBean;import com.marsjiang.myretrofiterrortest.myretrofit.MyGsonConverterFactory;import okhttp3.OkHttpClient;import okhttp3.logging.HttpLoggingInterceptor;import retrofit2.Call;import retrofit2.Callback;import retrofit2.Response;import retrofit2.Retrofit;public class MainActivity extends AppCompatActivity {    private Retrofit retrofit;    private String ipPortString;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ipPortString = "192.168.10。19:8080";        String url = "http://" + ipPortString + "/XiaoXiao/";        retrofit = new Retrofit.Builder()                .baseUrl(url)                .addConverterFactory(MyGsonConverterFactory.create())                .client(getOkHttpClient())                .build();        ApiCore userBiz = retrofit.create(ApiCore.class);        Call<Result<UserReturnBean>> call = userBiz.getLoginInfo();        call.enqueue(new Callback<Result<UserReturnBean>>() {            @Override            public void onResponse(Call<Result<UserReturnBean>> call, Response<Result<UserReturnBean>> response) {                if (response.isSuccessful()) {                    if (response.body().getData() == null) {                    }                    Log.e("infoooo", "normalGet:" + response.body() + "");                }            }            @Override            public void onFailure(Call<Result<UserReturnBean>> call, Throwable t) {                Log.e("infoooo", "normalGet:" + t.toString() + "");            }        });    }    /**     * 获取okhttp拦截器     *     * @return     */    public OkHttpClient getOkHttpClient() {        //日志显示级别        HttpLoggingInterceptor.Level level = HttpLoggingInterceptor.Level.BODY;        //新建log拦截器        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {            @Override            public void log(String message) {                Log.d("zcb", "OkHttp====Message:" + message);            }        });        loggingInterceptor.setLevel(level);        //定制OkHttp        OkHttpClient.Builder httpClientBuilder = new OkHttpClient                .Builder();        //OkHttp进行添加拦截器loggingInterceptor        httpClientBuilder.addInterceptor(loggingInterceptor);        return httpClientBuilder.build();    }}

嗯,这样每次就能打印出来了!

代码是最好的老师!

gitHub地址:

点击打开链接



还是那句话,做好自己,加油!

阅读全文
0 0