来自不同线程(Timer-1和EDT)的jsonRequest()方法的多次调用确实会相互干扰,甚至一个调用都将返回上一次调用的结果
我的CodeNameOne应用程序使用后台线程(Timer-1)每秒检索和显示REST服务中的数据,它允许用户发出命令,这些命令也从EDT线程发出REST调用。
private Map<String, Object> jsonRequest(String url, String body, String cmd, int timeoutMs) {
long startTs = System.currentTimeMillis();
try {
request = new ConnectionRequest();
request.setReadResponseForErrors(true);
// request.setTimeout(timeoutMs);
// Shai: Timeout in Codename One is currently limited to connection timeout and
// doesn't apply to read timeout so once a connection is made it will last
request.setHttpMethod(cmd);
request.setPost(cmd.equalsIgnoreCase("POST") || cmd.equalsIgnoreCase("PUT") || cmd.equalsIgnoreCase("PATCH"));
if (body != null) {
request.addRequestHeader("Accept", "application/json");
request.setContentType("application/json");
request.setRequestBody(body);
request.setWriteRequest(true);
}
request.setUrl(url);
NetworkManager.getInstance().addToQueueAndWait(request);
long duration = System.currentTimeMillis() - startTs;
Log.p(cmd + ": " + url + " " + duration + " ms");
if (request.getResponseCode() >= 400 || request.getResponseData() == null) {
Log.p("responseCode=" + request.getResponseCode() + " responseData=" + request.getResponseData());
return null;
}
Log.p(cmd + ": " + url + " " + new String(request.getResponseData()));
Map<String, Object> result = new JSONParser().parseJSON(new InputStreamReader(new ByteArrayInputStream(request.getResponseData()), "UTF-8"));
return result;
} catch (Exception e) {
problemHandler.handle(cmd, url, e);
}
return null;
}
实际上,多次调用的结果混杂在一起。 我希望每次对addToQueueAndWait()的调用都等待正确的结果,并在结果在那里时返回。 我观察到这个问题在Android上比在iOS或模拟器上更常见。
答案 0 :(得分:1)
我怀疑那是你所看到的。我看到请求是在类级别定义为变量的,所以我猜您正在看到一种典型的竞争情况,其中请求变量在发送时被替换,而到解析时则是另一个对象。
由于网络已经在单独的线程上运行(因此通常在 0 | 1 | 2
---+---+---
3 | 4 | 5
---+---+---
6 | 7 | 8
方法中确定),因此无需使用线程进行轮询。
我建议对响应完成后调用的单个调用使用计时器。
一个更好的方法是使用websockets:https://www.codenameone.com/blog/introducing-codename-one-websocket-support.html
使用websocket,服务器可以推送更新通知。这将节省您不断轮询服务器的需求。这样可以节省设备的电池寿命和服务器/设备上的资源。