6

我正在用 LibGDX 制作一个小游戏。我将玩家的用户名保存在本地以及服务器上。问题是应用程序没有等待调用结果,因此在线数据库的 ID 没有保存在本地。这是代码的整体流程:

//Create a new user object
User user = new User(name);

//Store the user in the online database
NetworkService networkService = new NetworkService();
String id = networkService.saveUser(user);

//Set the newly generated dbase ID on the local object
user.setId(id);

//Store the user locally
game.getUserService().persist(user);

在这段代码中,id变量没有被设置,因为saveUser函数立即返回。如何让应用程序等待网络请求的结果,以便我可以处理服务器通信的结果?

这是代码saveUser

public String saveUser(User user) {
    Map<String, String> parameters = new HashMap<String, String>();
    parameters.put("action", "save_user");
    parameters.put("json", user.toJSON());

    HttpRequest httpGet = new HttpRequest(HttpMethods.POST);
    httpGet.setUrl("http://localhost:8080/provisioner");
    httpGet.setContent(HttpParametersUtils.convertHttpParameters(parameters));

    WerewolfsResponseListener responseListener = new WerewolfsResponseListener();
    Gdx.net.sendHttpRequest (httpGet, responseListener);
    return responseListener.getLastResponse();
}

这是WerewolfsResponseListener课程:

class WerewolfsResponseListener implements HttpResponseListener {
    private String lastResponse = "";
    public void handleHttpResponse(HttpResponse httpResponse) {
        System.out.println(httpResponse.getResultAsString());
        this.lastResponse = httpResponse.getResultAsString();    
    }

    public void failed(Throwable t) {
       System.out.println("Saving user failed: "+t.getMessage());
       this.lastResponse = null;
    }

    public String getLastResponse() {
        return lastResponse;
    }
}
4

2 回答 2

4

您看到的异步来自Gdx.net.sendHttpRequest. WerewolfsResponseListener每当请求返回时,都会调用第二个参数 (your ) 上的方法。成功/失败方法不会被“内联”调用。

有两种基本方法可以处理这样的回调结构:“轮询”或“事件”。

通过轮询,您的主游戏循环可以“检查”responseListener它是否成功或失败。(您需要稍微修改您当前的侦听器以消除成功案例和空字符串的歧义。)一旦您看到有效的响应,您就可以这样做user.setId()

使用“事件”,您可以将user.setId()调用放在responseListener回调中,这样只要网络响应,它就会执行。这更适合 Libgdx 网络 API。(这确实意味着您的响应侦听器将需要对该user对象的引用。)

无法在线“等待”网络调用返回。Libgdx 网络 API(正确)假设您不想在渲染线程中无限期地阻塞,因此它不是为此而结构化的(侦听器将作为 Runnable 排队,因此它最早可以运行在下一次渲染调用时) .

于 2013-04-24T23:46:25.033 回答
1

我不会向任何人推荐这个,但如果你需要以一种快速而肮脏的方式测试某些东西并且绝对必须阻止,这将起作用。没有超时,所以再次为绝对的污秽做好准备:

long wait = 10;
while(!listener.isDone())
{
    Gdx.app.log("Net", "Waiting for response");
    try
    {
        Thread.sleep(wait *= 2);
    }
    catch (InterruptedException e)
    {
        e.printStackTrace();
    }
}

public static class BlockingResponseListener implements HttpResponseListener
{
    private String data;
    private boolean done = false;
    private boolean succeeded = false;

    @Override
    public void handleHttpResponse(HttpResponse httpResponse)
    {
        Gdx.app.log("Net", "response code was "+httpResponse.getStatus().getStatusCode());
        data = httpResponse.getResultAsString();
        succeeded = true;
        done = true;
    }

    @Override
    public void failed(Throwable t)
    {
        done = true;
        succeeded = false;
        Gdx.app.log("Net", "Failed due to exception ["+t.getMessage()+"]");
    }

    public boolean succeeded()
    {
        return succeeded;
    }

    public boolean isDone()
    {
        return done;
    }

    public String getData()
    {
        return data;
    }

}
于 2014-02-23T08:24:00.597 回答