不知何故,循环没有正确执行(我相信),当我使用循环时,对服务器的调用永远不会完成(没有循环时会完成)
请参见以下代码
客户端:主控制器
class MainController
{
private final AtomicLong counter;
private final HashMap<Long, Object> callResults;
public MainController(){
counter = new AtomicLong();
callResults = new HashMap<>();
}
public Login getLoginByUsername(String username)
{
long callID = counter.incrementAndGet();
System.out.println("Start call");
ServerConnection.get("myURL",null, new JsonHttpResponseHandler(){
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response){
try {
System.out.println("Call success, enter result:");
callResults.put(callID, new CallResult(Login.parseFromJson(response)));
System.out.println(callResults.get(callID));
} catch (JSONException e) {
e.printStackTrace();
}
}
});
System.out.println("start waiting");
while(callResults.get(callID) == null){
System.out.print(".");
}
System.out.println("waiting over, return result:");
System.out.println(callResults.get(callID));
//return (Login) callResults.remove(callID).content;
return null;
}
}
import com.loopj.android.http.*;
import cz.msebera.android.httpclient.HttpEntity;
public class ServerConnection {
private static final String BASE_URL = "http://1.3.3.7:8080/";
private static AsyncHttpClient client = new AsyncHttpClient();
public static void get(String url, RequestParams params, JsonHttpResponseHandler responseHandler) {
client.get(BASE_URL+url, params, responseHandler);
}
}
我认为这就是问题所在:循环阻止了异步REST调用的进行,从而使其无法终止。
我的问题是:A)如何将从服务器收到的Login-Object返回到首先调用MainController.getLoginbyUsername-function的函数?
B)我试图用于等待的while-loop是怎么回事?为什么主体(print(".“);
)不会被执行,更重要的是,为什么它会停止REST调用表单的执行/完成?
编辑:增加了问题B,可能会提供一个更容易找到快速解决方案的方法
编辑到更新:很抱歉没有把这一点说得足够清楚:任何需要我修改调用函数的建议(例如,像LiveData
或Rxjava
这样的观察者模式,或者Leo Pelozo提供的其他非常好的建议)都是不可行的。我至少测试了Leo Pelozos的建议,底层代码根本不允许这样做。我失去了对参数的访问,不能再利用函数返回了。我知道,重新设计底层系统是最好的做法,但现在这根本超出了范围...
谢谢你的帮助!我找到了一个适合我案子的解决方案。
首先,由于这只是一个原型,我并不真的需要我的请求是异步的,所以我将ServerConnection
改为使用SynchTtpClient
:
public class ServerConnection {
private static final String BASE_URL = "http://10.203.58.11:8080/";
private static SyncHttpClient client = new SyncHttpClient();
public static void get(String url, RequestParams params, JsonHttpResponseHandler responseHandler) {
client.get(getAbsoluteUrl(url), params, responseHandler);
}
}
然后,Android不允许我在主线程上执行请求。对于AsynchTtpClient
来说,这不是一个问题,因为异步部分是在自己的线程中处理的。所以我不得不在我的请求中添加线程。因此,我的maincontroller
现在看起来如下所示:
public class MainController
{
private final AtomicLong counter;
private final HashMap<Long, CallResult> callResults;
public MainController(){
counter = new AtomicLong();
callResults = new HashMap<>();
}
public Login getLoginByUsername(String username)
{
long callID = counter.incrementAndGet();
new Thread(new Runnable() {
@Override
public void run() {
ServerConnection.get("person-login-relations?byUsername="+username,null, new JsonHttpResponseHandler(){
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response){
try {
callResults.put(callID, new CallResult(Login.parseFromJson(response)));
System.out.println(callResults.get(callID));
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
}) .start();
while(callResults.get(callID) == null){
//wait
}
return (Login) callResults.remove(callID).content;
}
}
我想我用来等待的while-loop现在起作用了,因为它没有阻塞负责执行和处理请求的线程。不过,我不完全确定。
诚然,这可能不是理想的解决方案,但考虑到我的具体情况,这是最可行的。
几个月后,我将被要求重新工作我现在扩展的应用程序,以连接到客户机。在这一点上,我将确保实施您的大部分建议!因此,对于任何阅读此解决方案的人来说:这里是一个变通方法,因为我不需要异步请求,也不应该更改调用您在这里看到的方法的函数!我建议你还是阅读其他的回复,因为它们在质量上更好!
问题内容: 我有一个发送Ajax命令的系统,该命令返回一个带有功能的脚本块。将此数据正确插入DIV后,我希望能够调用此函数来执行所需的操作。 这可能吗? 问题答案: 我想以这种形式正确解释您的问题:“好的,我已经用完所有的Ajax东西了;我只想知道从那时起任何时候都可以调用插入到DIV中的JavaScript函数吗? ,也就是说,我不想在上下文中将其称为“回调返回”。 好的,如果您的意思是这样,那
问题内容: 我有一个发出异步请求的函数。我如何从中返回响应/结果? 我尝试从回调中返回值,以及将结果分配给函数内部的局部变量并返回该局部变量,但这些方法均未真正返回响应(它们都返回或变量的初始值为任意值) 。 使用jQuery函数的示例: 使用node.js的示例: 使用承诺块的示例: 问题答案: 在 一 中的Ajax代表 异步 。这意味着发送请求(或接收响应)已从正常执行流程中删除。在您的示例中
使用promise的块的示例:
问题内容: 我如何使这个小功能“ imageExists”返回ajax请求是否成功? 问题答案: 我相信您将必须使用同步模式并使用单独的变量来存储返回值。
问题内容: 我有一个发出Ajax请求的函数。我如何从中返回响应? 我尝试从回调中返回值,以及将响应分配给函数内部的局部变量并返回该局部变量,但这些方法均未真正返回响应。 问题答案: 问题 在一中的Ajax代表异步。这意味着发送请求(或更确切地说接收响应)已从正常执行流程中删除。在你的示例中,立即返回并且在调用;作为回调传递的函数之前执行下一条语句。 这是一个类比,希望可以使同步流和异步流之间的区别
问题内容: 谁能告诉我如何将值作为函数的返回值返回。 当您点击注册表格中的提交时,上述功能就会触发(很明显)。问题是,无论响应是什么,此表单都将提交,并且警告框有时不显示任何内容(空白),有时根本不显示。但是,如果我将结尾更改为手动[即用] 替换,则正确的值将显示在警报框中。 PS我比JavaScript的菜鸟还差,因此也欢迎提出一般性改进代码的建议。 问题答案: 问题是,直到……等待……状态改变