Java 调用OnFailure并引发IOException,但已发布数据

Java 调用OnFailure并引发IOException,但已发布数据,java,android,retrofit,Java,Android,Retrofit,这是我的网络请求示例 networkAPI.postData(myData).enqueue(new Callback<MyResponse>() { @Override public void onResponse(Call<MyResponse> call, Response<MyResponse> response) { if (response.code() == 201) { // succ

这是我的网络请求示例

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) {

    }
});
networkAPI.postData(myData).enqueue(新回调(){
@凌驾
公共void onResponse(调用、响应){
if(response.code()=201){
//成功
}
}
@凌驾
失败时公共无效(调用调用,可丢弃的t){
}
});
这是我应该只调用一次的请求,因为我有一次可用的凭证代码。如果我立即关闭网络连接,或者如果调用此方法后它立即断开连接,则它将移动到throwable中带有
IOException
onFailure
方法,该方法通常指连接错误,但关键是数据已发布到服务器,凭证代码已被使用,问题是这里调用了
onFailure
方法


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

我不知道您的后端是什么,但在C#WebApi中,在服务器端,您可以通过
响应检查客户端是否仍然连接。isClient已连接
,但我相信此标志仅用于正常的tcp断开连接。如果客户突然关闭了他的互联网,那就行不通了。这仅仅是由于http(和底层tcp)的性质

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


最好的办法是让客户以某种方式查看过去兑换的代金券。或者在“刷新”页面或其他页面上,您可以自动检查是否有过去的凭证兑换尝试(通过另一种Web服务方法),并适当显示响应

我随机猜测,在特定的错误场景中,您的响应已动态更改(甚至可能为空)。由于您需要类型为
MyResponse
的对象,当返回动态更改的响应时,您的改装调用可能无法处理该响应,因此跳转到
onFailure
方法。在这种情况下,您的数据会被发布到后端,而改型会在故障时进入
onFailure

可能的解决方案

首先尝试找出发生特定错误时的响应,并尝试为其建立模型(使用
void
表示
null


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

中,根据问题,我相信您通过网络正确发布了数据,并且当服务器尝试给您响应时,您的系统由于网络故障而失去连接,改装会发出故障回调

解决方案


当执行因网络故障而达到onfailure时,您可以调用重试api对话框,并要求用户再次发送api并正确获得响应。因此,除非用户得到适当的响应,否则他将无法继续前进。

我认为改装方法正在按预期工作。如果您已将一些数据发布到服务器,并且即使已连接internet,您的服务器应用程序处理请求的时间也可能太长,并且一旦服务器以成功状态响应,应用程序端请求就会超时。关键是,有几种情况下,您可能会面临相同的问题

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

现在,使用此特殊标志指示是否使用凭证有什么好处?主要优点是,您可以在以后同步使用凭证的状态。您可以考虑在应用程序启动中检查标志,以便在打开任何先前标志的情况下,在服务器和客户端之间进行同步。p>
我的答案的关键思想是构建一个服务器-客户端握手机制,在该机制中,您可以确认凭证是否可用

这是一个后端问题IMO。此类任务应作为完成,并且应仅在最后才执行

若您需要确切的结果,那个么您就有和(在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;

我知道您有一次性凭证代码,但如果网络出现故障,肯定有办法获取凭证的原因。是吗?@I_of____________________________________________。在这种情况下,我无法确定数据是否已发布。API调用已经完成,我无法从服务器端请求任何要处理的内容。很明显,您存在某种连接错误,如果没有看到您的实际网络调用,我将无法帮助您。这个呼叫对邮递员有效吗?这应该在服务器端进行管理。听起来好像写入数据库不是ato