在Android中使用RxJava处理Restful Api格式的错误响应

发布于 2022-09-03 09:23:45 字数 1521 浏览 11 评论 0

最近使用 rxjava 搭配 retrofit 来进行网络访问 API,但不知道该怎样进行错误处理。
因为我的响应格式是这样的:

正确时:

{
  "id": 1,
  "username": "lazyS_WSD_Wd",
  "mobile": "18912345678",
  "email": "",
  "avatar_url": "http://api.xxxx.com/images/default_avatar.png",
  "last_address_id": 1,
  "last_ip": "::1",
  "last_device_type": "android",
  "last_device_id": "99000566712916"
}

而不是这样的:

{
    "status": 200,
    "message": "请求成功",
    "data": {
        "id": 1,
        "username": "lazyS_WSD_Wd",
        "mobile": "18912345678",
        "email": "",
        "avatar_url": "http://api.xxxx.com/images/default_avatar.png",
        "last_address_id": 1,
        "last_ip": "::1",
        "last_device_type": "android",
        "last_device_id": "99000566712916"
    }
}

错误时:

是这样的:

{
  "message": "未找到该地址",
  "status": 404,
}

这时的HTTP响应状态也是404

而不是这样的:

{
    "status": 404,
    "message": "未找到该地址",
    "data": null
}

所以当请求成功,但返回的是用户自定义的错误时,我不能把该自定义的错误解析成指定的错误对象。

以前没有用 rxjava 时,我是这样处理的:

Response<T> response = call.execute();
if (BuildConfig.DEBUG) {
    Logger.json(response.raw().toString());
}
if (response.isSuccess()) {
    result = response.body();
} else {
    responseError = GsonHelper.builderGson().fromJson(response.errorBody().string(), ResponseError.class);
}

请问如果用 rxjava 的话,应该怎样进行处理?先谢谢了!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

殊姿 2022-09-10 09:23:46

我的做法是将正常或者异常都封装到一个Result对象中。如果是成功可以通过getResult获取到我们需要的对象;失败时也可以拿到异常码和异常信息。

public class BaseResult<T> implements Serializable {
    private boolean success;//表示是否成功
    private String errCode;
    private String errMsg;
    private T result;//被封装的正确结果对象

然后分两种情况处理异常。一种是直接retrofit2一次调用出现异常;另一种是一次调用拿到结果后又链式调用第二个api时,第一次出现异常。

第一种情况很简单。因为封装的BaseResult可以判断出是否发生异常(success字段)

userService.findUserList()
                .subscribe(userListBaseResult -> {
            if (!userListBaseResult.isSuccess()) {
                fail();//直接进行错误处理
                return;
            }
            List<User> userList = userListBaseResult.getResult();
            //正常流程
        });
        

第二种情况。可以选择链式,因为美观;也可以选择两次分开调用。如果两次分开调用的话,第一次的异常处理同上。如果选择链式:

//这里先根据id查到用户后更新用户信息
userService.findUser(5)
                .flatMap(userBaseResult -> {
                    if (!userBaseResult.isSuccess()) {
                        //封装自定义异常,重新传递下去
                        return Observable.error(new BusinessRuntimeException(userBaseResult.getErrCode()));
                    } else {
                        User user = userBaseResult.getResult();
                        user.setAddress("XXX");
                        return userService.updateUser(user.getId(), user);
                    }
                })
                .subscribe(updateResult -> {
                    //正常走到这里
                    if (!updateResult.isSuccess()) {
                        //异常
                    } else {
                        //正常处理
                    }
                }, exception -> {
                    //findUser发生异常走到这里
                    if (exception instanceof BusinessRuntimeException) {
                        //异常处理
                    }
                });
自此以后,行同陌路 2022-09-10 09:23:46
public abstract class BaseModel {
    public int status;
    public String message;
}

public class XX extends BaseModel {
    //
}
XX xx = new XX();
xx.status = 404;
xx.message = "Not Found";
Observable
        .just(xx)
        .flatMap(x -> {
            if (xx.status == 200) {
                return Observable.just(x);
            } else {
                return Observable.error(new Exception(xx.message));
            }
        })
        .subscribe(new Subscriber<XX>() {
            @Override
            public void onCompleted() {
            }
            
            @Override
            public void onError(Throwable e) {
                e.printStackTrace();
            }
            
            @Override
            public void onNext(XX xx) {
                System.out.println(xx);
                //要么就不要上面的flatMap,直接在这判断处理。
            }
        });
锦爱 2022-09-10 09:23:46

参考:Retrofit+RxJava 优雅的处理服务器返回异常、错误http://blog.csdn.net/jdsjlzx/...

贱贱哒 2022-09-10 09:23:45

我通过查看 RxJavaCallAdapterFactory 这个类的代码,自己解决了这个问题。
我发现当使用RxJava创建observables时,可以有三种不同的返回类型

  • Observable<Foo>

  • Observable<Response<Foo>>

  • Observable<Result<Foo>>
    而Observable<Foo>这种返回类型的OnErrorAction里的throwable参数是HttpException这种类型的,这个HttpException里有 Response 对象,自然的,就可以拿到 errorBody 来进行我所想要的处理了。

我定义了一个类 ResponseError来接收错误消息的响应。

public class ResponseError {

    public int status;
    public String message;

    // getter 和 setter 方法略

    // 主要是这个方法
    public static ResponseError handle(Throwable throwable) {
        ResponseError error = null;
        if (throwable instanceof HttpException) {
            HttpException exception = (HttpException) throwable;
            try {
                error = new Gson().fromJson(exception.response().errorBody().string(),
                                ResponseError.class);
            } catch (Exception e) {
                if (e instanceof JsonParseException) {
                    error = new ResponseError(HTTP_SERVER_ERROR, "服务器出错");
                } else {
                    error = new ResponseError(HTTP_UNKNOWN_ERROR, "未知错误");
                }
            }
        } else {
            error = new ResponseError(HTTP_UNKNOWN_ERROR, "未知错误");
        }
        if (BuildConfig.DEBUG) {
            throwable.printStackTrace();
        }

        return error;
    }
}

然后再定义了一个Action:

public abstract class ErrorAction implements Action1<Throwable> {

    @Override
    public void call(Throwable throwable) {
        ResponseError error = ResponseError.handle(throwable);
        call(error);
    }

    public abstract void call(ResponseError error);
}

这样,在使用 Rxjava 链式操作的时候就可以这样了

mRestApiClient.accountService()
        .login(username, password)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Action1<List<Business>>() {
            @Override
            public void call(List<Business> businesses) {
                // do something
            }
        }, new ErrorAction() {
            @Override
            public void call(ResponseError error) {
                // do something
            }
        });

记录在此,希望能帮到后面的朋友!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文