如何在重播对用户的所需响应之前拦截需要用户操作的响应

时间:2017-09-13 01:07:21

标签: android okhttp3

我有一个相当独特的问题,我必须解决。我正在开发一个应用程序,该应用程序使用本地网络层与Android中的旧版okhttp客户端,我们希望使用Retrofit和OKHttp3。

我们遇到的问题是我们的服务可能会返回对用户请求的响应,该请求包含用户在允许原始请求执行之前必须执行的一个或多个操作,从而返回所需的响应。

有点像这样。用户尝试登录,但他们是新用户,而服务通过一系列信息收集操作进行响应。如果用户取消他们不登录,但如果用户执行一系列操作,则重播原始登录请求并且用户登录。

我正在密切关注OkHttp3提供的Interceptor接口作为实现此目的的手段。现在我知道我可以拦截任何响应并修改它或做其他事情,但接口方法必须最后返回一个类型为Response的值。但是,我需要能够“保持/阻止”在用户之前发生的返回A:取消服务所需的操作,或者B:成功完成这些操作。

这是我到目前为止所做的。

private static class ServerActionInterceptor implements Interceptor {

    @Override
    public Response intercept(Chain chain) throws IOException {
        Response response = chain.proceed(chain.request());
        Gson gson = new Gson();
        ServicesResponse serviceResponse = null;
        if (response.body() != null) {
            serviceResponse = gson.fromJson(response.body().string(), ServicesResponse.class);
        }
        if (serviceResponse != null) {
            if (serviceResponse.getServerActions() != null && serviceResponse.getServerActions().size() > 0) {
                //handle server actions

                handleServerActions(serviceResponse);//this must complete before we can return chain.proceed IF there are actions the user must take.
            }
        }
        return chain.proceed(chain.request());
    }
    //this method may end up returning a value
    private void handleServerActions(ServicesResponse serviceResponse) {
        //process server actions 
    }
}

它不是很多,大多数都会发生在handleServerActions中,而且老实说这个应用非常特别。但问题的核心是,我应该使用什么方法,以便如果没有用户请求的serverActions,或者用户已经完成了操作,那么返回将会发生,因此真正的响应已准备好传递给客户端?

感谢。

1 个答案:

答案 0 :(得分:1)

由于发表评论,我想我会分享我的解决方案。

它涉及一个实现Callback<T>的自定义抽象类。

这只是一个一般示例,实际实现将取决于您项目的业务规则。

public abstract class CustomCallback<T extends CustomResponse> implements Callback<T> {
        private CustomExcetption encounteredException;
        private Class<T> clazz;

        public CustomCallback(Class<T> clazz) {
            this.clazz = clazz;
        }

        @Override
        public void onResponse(@NonNull Call<T> call, @NonNull Response<T> response) {

            if (response.body() != null) {
                T body = response.body();
                i
                if (body != null && body.hasCustomActions() != null && body.hasCustomActions().size() > 0) {
                    handleCustomAction(body);
                } else {
                    onSuccessfulResponse(body);
                }

            } else if (response.errorBody() != null) {
                  onFailureResponse(exception);
            }
        }

        @Override
        public void onFailure(@NonNull Call<T> call, @NonNull Throwable throwable) {
            onNetworkFailure(call, exception);
        }

        public abstract void onSuccessfulResponse(@Nullable T response);

        public abstract void onFailureResponse(CustomException exception);

        public abstract void onNetworkFailure(Call<T> call, CustomException exception);

        public void handleCustomAction(@NonNull final T body, final String path) {
          //handle custom actions.
          if(customActionsHandledSuccessfully) {
              onSuccessfulResponse(body);
          } else {
              //create your exception somehow
              CustomException createdException = new CustomException();
              onFailureResponse(createdException);
          }
        }
    }  

用法示例: 不断完善对SomeResponse.class的引用是实现我所需要的,而在其他人中可能不需要。它用于gson序列化,因为我需要知道响应的具体类以正确地对其进行序列化。

service.someApi().enqueue(new CustomCallback<SomeResponse>(SomeResponse.class) {
            @Override
            public void onSuccessfulResponse(@Nullable SomeResponse response) {
            }

            @Override
            public void onFailureResponse(CustomException exception) {
            }

            @Override
            public void onNetworkFailure(Call<SomeResponse> call, CustomException exception) {
            }
   });