改进全局错误句柄

时间:2016-12-10 04:41:33

标签: java android retrofit retrofit2

嗯,我们知道,如果服务器的响应格式如下:

{data: T,status: 200,error:""}

很容易得到这样的基本回复:

public class HttpResult<T> {
    public int satus;
    public String error;
    public T data;
}

但是,如果服务器在成功时返回JSON对象并返回另一个JSON对象,该怎么办? 失败时的JSON对象,例如:

{
  "error": "Consumer key missing.",
  "status": 401
}

现在,对于成功和错误结果,我如何编写基类来封装响应?

或者我应该让GSON在这两种情况下解析不同的JSON对象?

PS:我在这个项目中使用GSON并改造+ rxjava ......

有人能给我一些建议吗?

提前致谢

2 个答案:

答案 0 :(得分:0)

在GSON库中,您无需处理它,因为如果您的参数丢失,它将自动返回null。

public class HttpResult<T> 
{
public int satus;
public String error;
public T data;
}

在上面的课程中,你会得到T为空。

答案 1 :(得分:0)

当您将RxJava与Retrofit一起使用并将请求返回类型定义为Observable<Result>,其中Result是要将响应反序列化的对象类型时,RxJava仅自动发出HTTP状态代码在&lt之间的响应; 200,300)被认为是成功的..每个其他使用不同状态代码返回的响应都被视为失败并将抛出HttpException,因此您可以在onError回调中执行错误处理,如下所示:

create(ApiService.class).someRequest()
    .subscribe((result) -> {
        // process your successful result
    }, (throwable) -> {
        if(throwable instanceof HttpException){
            switch (((HttpException) throwable).code()) {
                case 401: // handle this type of error
                default: // do whatever you want when you don't expect this type of error to happen
            }
        } else {
            // error returned is not related to a failed response 
            // and is probably a result of an exception along the 
            // way in the stream ( wrong (de)serialization, no network
            // connection or whatever you might mess up in the stream ) 
        }
    })

但是,通过您提供的返回语法,我猜您的服务器会忽略HTTP标准,并在json正文中向您发送状态代码。虽然这不是一个好的方法,你可能想与谁负责你的后端讨论这个,当然有一个方法。没有你的帮助,改造本身无法解决这个问题,因为它不知道哪个字段对应于状态代码。但您可以修改流,使其行为符合您的要求。如果您按照描述的方式使用返回的HttpResult定义请求,那么您可以执行以下操作:

create(ApiService.class).someRequest()
    .map((result) -> {
        if(result.status >= 200 && result.status < 300) return result.data;
           else throw new MyHttpException(result.error, result.status);
    })
    .subscribe((result) -> {
        // process your successful result
    }, (throwable) -> {
        if(throwable instanceof MyHttpException){
            switch (((MyHttpException) throwable).code) {
                case 401: // handle this type of error
                default: // do whatever you want when you don't expect this type of error to happen
            }
        } else {
            // error returned is not related to a failed response 
            // and is probably a result of an exception along the 
            // way in the stream ( wrong (de)serialization, no network
            // connection or whatever you might mess up in the stream ) 
        }
    })


public class MyHttpException extends RuntimeException {

    public String message; 

    public int code;

    public MyHttpException(String message, int code) {
        super(message);
        this.message = message;
        this.code = code;
    }
}

您可以通过将地图运算符封装到Transformer中来稍微涂抹一下,这样您就可以通过.compose()应用它。不幸的是,在Retrofit的人接受拉取请求(或由他们自己实现)为所有请求定义全局变换器之前,没有什么好办法全局地做到这一点。