Synchronous responses to `Gdx.net.sendHttpRequest` in LibGDX

白昼怎懂夜的黑 提交于 2019-12-10 15:11:00

问题


I'm making a small game in LibGDX. I'm saving the player's username locally as well as on a server. The problem is that the application is not waiting for the result of the call so the online database's ID is not saved locally. Here's the overall flow of the code:

//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);

in this code, the id variable is not getting set because the saveUser function is returning immediately. How can I make the application wait for the result of the network request so I can work with results from the server communication?

This is the code for 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();
}

This is the WerewolfsResponseListener class:

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

回答1:


The asynchrony you are seeing is from Gdx.net.sendHttpRequest. The methods on the second parameter (your WerewolfsResponseListener) will be invoked whenever the request comes back. The success/failure methods will not be invoked "inline".

There are two basic approaches for dealing with callbacks structured like this: "polling" or "events".

With polling, your main game loop could "check" the responseListener to see if its succeeded or failed. (You would need to modify your current listener a bit to disambiguate the success case and the empty string.) Once you see a valid response, you can then do the user.setId() and such.

With "events" then you can just put the user.setId() call inside the responseListener callback, so it will be executed whenever the network responds. This is a bit more of a natural fit to the Libgdx net API. (It does mean your response listener will need a reference to the user object.)

It is not possible to "wait" inline for the network call to return. The Libgdx network API (correctly) assumes you do not want to block indefinitely in your render thread, so its not structured for that (the listener will be queued up as a Runnable, so the earliest it can run is on the next render call).




回答2:


I would not recommend this to any human being, but if you need to test something in a quick and dirty fashion and absolutely must block, this will work. There's no timeout, so again, be prepared for absolute filth:

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

}


来源:https://stackoverflow.com/questions/16195608/synchronous-responses-to-gdx-net-sendhttprequest-in-libgdx

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!