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

Rob*_*ert 5 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);
Run Code Online (Sandbox Code Playgroud)

在此代码中,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();
}
Run Code Online (Sandbox Code Playgroud)

这是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;
    }
}
Run Code Online (Sandbox Code Playgroud)

P.T*_*.T. 4

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

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

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

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

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