调用了OnFailure并抛出IOException但发布了数据

时间:2018-07-13 04:44:39

标签: java android retrofit

这是我的网络请求示例

networkAPI.postData(myData).enqueue(new Callback<MyResponse>() {
    @Override
    public void onResponse(Call<MyResponse> call, Response<MyResponse> response) {
         if (response.code() == 201) {
             // success
         }
    }
    @Override
    public void onFailure(Call<MyResponse> call, Throwable t) {

    }
});

这是我只能使用一次的优惠券代码,因此我只能致电一次的请求。如果我立即关闭网络连接或调用此方法后网络连接立即断开,则它将移至onFailure中带有IOException的throwable中,这通常表示连接错误,但关键是数据已发布到服务器并且使用了优惠券代码,问题是这里调用了onFailure方法。

我确信这不是解析失败,因此我也尝试使用Void。为什么onResponse即使在发布数据后也没有被调用。如何克服这种情况?

5 个答案:

答案 0 :(得分:5)

我不知道您的后端是什么,但是在服务器端的C#WebApi中,您可以检查客户端是否仍通过Response.IsClientConnected连接,但是我认为该标志仅用于正常的TCP断开连接。如果客户端突然关闭互联网,那将是行不通的。这仅仅是由于http(和底层tcp)的本质造成的

此外,我认为值得一提的是,总是存在请求到达服务器但响应未到达客户端的可能性。根本无法保证在没有成功响应客户端的情况下服务器不会处理凭证。客户端可以发送请求,一旦您准备好返回状态码200,客户端就可能断开连接。 Web服务设计中应始终考虑这一点。

最好的办法是给客户一些查看过去兑换的凭单的方式。或在页面新鲜的页面上,或者您可以自动检查是否有过过去的凭证兑换尝试(通过另一种Webservice方法)并适当显示响应。

答案 1 :(得分:2)

我认为改造方法可以按预期工作。可能会发生这种情况,因为您已经向服务器发布了一些数据,并且即使连接了Internet,服务器应用程序仍需要花费大量时间来处理请求,并且一旦服务器以成功状态返回响应,应用程序侧请求就会超时。关键是有几种这样的情况,您可能会遇到相同的问题。

我可以通过建立有关使用凭证的服务器-客户端握手来为这个特定问题提供一个合适的解决方案。您可能会考虑使用本地数据库设置(它可以是可以在本地处理的任何存储机制)来跟踪您迄今为止尝试使用的凭证代码。在这种情况下,启动请求时,将在本地生成一个标志,并且在从服务器端获得成功响应后,该标志将被清除。

现在,使用此特殊标志指示是否使用凭证的优点是什么?主要优点是您可以稍后在receiving a broadcast when your internet is connected again上同步使用凭证的状态。您可能会考虑在应用程序启动时也检查该标志,以便在打开任何先前标志的情况下在服务器和客户端之间进行同步。

我的答案的关键思想是建立服务器-客户端握手机制,在其中可以确认凭证是否可用。

答案 2 :(得分:1)

我的随机猜测是,在您的特定错误情况下,您的响应已动态更改(甚至可能为null)。由于您期望的对象类型为MyResponse,因此当返回动态更改的响应时,您的改装调用可能无法处理该响应,因此跳转到onFailure方法。在这种情况下,您的数据将被发布到您的后端,而改造将被发布到onFailure

Possible Solution

在出现特定错误的情况下,首先尝试找出响应,然后尝试为其建立模型(对void使用null

通过使用反序列化器在运行时处理动态错误响应和适当的响应,尝试 dynamically parsing json 。因此,通过使用反序列化器,您可以使错误响应(发布数据的情况)也出现在onResponse

答案 3 :(得分:1)

根据我认为您在网络上正确发布数据的问题,并且当服务器尝试给您响应时,您的系统由于网络故障而失去了连接,并且进行了故障回调。

解决方案

由于网络故障导致执行失败时,您可以调用重试api对话框,并要求用户再次发送api并正确获得响应。因此,直到并且除非给用户适当的响应,否则他将被阻止进一步移动。

答案 4 :(得分:0)

这是一个后端问题 IMO。此类任务应以 transaction 的形式完成,并且应仅在最后完成。

如果需要确切的结果,则可以使用shutdown functionsignore user abort (在PHP中。我相信在其他平台上也会有类似的事情)来执行提交操作。我更喜欢前者。


这是PHP的示例伪代码。

/**
Define a global variable to identify whether the execution completed 
successfully or an error (such as client disconnection) occurred 
*/
$isProgramExecutionSuccessful = FALSE;

/**
shutdown function to execute finally
*/
function onShutdown() {
    $error = error_get_last();
    if ( $isProgramExecutionSuccessful == TRUE ) {
        // commit transactions here
    }
}

/**
Register shutdown function
*/
register_shutdown_function('onShutdown');

//Do database operations as transactions here

/**
At the end flag execution as successful
*/
$isProgramExecutionSuccessful = TRUE;