LibGDX中对`Gdx.net.sendHttpRequest`的同步响应

时间:2013-04-24 15:09:38

标签: asynchronous libgdx

我在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;
    }
}

2 个答案:

答案 0 :(得分:4)

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

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

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

使用“events”,您可以将user.setId()调用放在responseListener回调中,这样只要网络响应就会执行。这对Libgdx net API来说更加自然。 (这确实意味着您的响应侦听器需要对user对象的引用。)

无法“等待”内联网络呼叫返回。 Libgdx网络API(正确地)假设您不希望在渲染线程中无限期地阻塞,因此它没有为此构造(侦听器将作为Runnable排队,因此它最早可以运行在下一个渲染调用中)

答案 1 :(得分: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;
    }

}