【问题标题】:Retrofit "IllegalStateException: Already executed"改造“IllegalStateException:已执行”
【发布时间】:2016-05-07 17:46:56
【问题描述】:

我有一个 ID 喜欢每 5 秒运行一次的 Retrofit 网络调用。我当前的代码:

Handler h = new Handler();
int delay = 5000; //milliseconds

h.postDelayed(new Runnable() {
    public void run() {
        call.enqueue(new Callback<ApiResponse>() {
            @Override
            public void onResponse(Response<ApiResponse> response) {
                Log.d("api", "response: " + response.body().getPosition().getLatitude().toString());
            }

            @Override
            public void onFailure(Throwable t) {

            }
        });
        h.postDelayed(this, delay);
    }
}, delay);

这会运行一次,但随后会抛出以下内容:

java.lang.IllegalStateException:已经执行。 在改造 2.OkHttpCall.enqueue(OkHttpCall.java:52) 在 retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall.enqueue(ExecutorCallAdapterFactory.java:57) 在 orbyt.project.MyFragment$1.run(MyFragment.java:93)

这里有什么问题?

作为奖励:有什么更好的方法来处理这个问题?每次更新都会更新地图。我正在考虑尝试使用 Rx,但不确定这是否是一个合适的用例,或者如何实现它。

【问题讨论】:

  • 您的网络调用是否可能花费超过 5 秒,所以当第二次迭代开始时,第一次迭代还没有完成?延迟不会在第一次迭代结束时开始,而是从您调用第一次迭代的时间开始 5 秒
  • @TooManyEduardos 我知道第一个电话正在完成,因为我正在记录响应,实际上正在获取数据。
  • 但日志只显示接收到的数据,而不是网络连接完成。它可能仍在 5 秒窗口内关闭元素。这只是一个想法,但尝试将延迟增加到 15 秒左右,看看问题是否消失
  • @TooManyEduardos 将延迟更改为 15 秒,但仍然出现相同的错误。
  • 我不明白这里有什么不清楚的地方。它告诉你什么不起作用,以及为什么。如果有疑问,请参阅文档square.github.io/okhttp/2.x/okhttp 它明确表示Throws: IllegalStateException - when the call has already been executed. 您的调用已经执行,因为这就是您想要的 - 重复调用 - 并抛出 IllegalStateException。这里没有什么令人惊讶的。

标签: android retrofit okhttp rx-android retrofit2


【解决方案1】:

Call 只能使用一次。 Its documentation告诉你如何多次使用:

使用clone()可以多次调用相同的参数到同一个webserver;这可用于实现轮询或重试失败的调用。

因此,异步使用call.clone().enqueue(..)同步分别使用call.clone().execute(),以确保您有一个新鲜的、未执行的Call每个请求。

【讨论】:

  • 嗨@Jake Wharton,我正在多次调用同一个API: if( call.isExecuted() ) { call.cancel(); } call.clone().enqueue(..) ,我只想接收来自最后/最新呼叫的响应,但每次呼叫都得到响应?
  • @Deven 如果您一次将 Ok 限制为单个请求,这可能是可靠可行的 new Retrofit.Builder().callFactory(new OkHttpClient.Builder().dispatcher(new Dispatcher().setMaxRequests(1).setMaxRequestsPerHost(1)).build()).build();我确实看到多个排队的请求完全乱序。
  • 我有一个疑问。我可以用 call.cancel() 代替那个吗?
猜你喜欢
  • 1970-01-01
  • 2017-02-12
  • 1970-01-01
  • 2020-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-09
相关资源
最近更新 更多