2013-04-24 31 views
5

Tôi đang tạo một trò chơi nhỏ trong LibGDX. Tôi đang lưu tên người dùng của người chơi cục bộ cũng như trên máy chủ. Vấn đề là ứng dụng không chờ kết quả của cuộc gọi để ID của cơ sở dữ liệu trực tuyến không được lưu cục bộ. Dưới đây là dòng chảy chung của các mã:Phản hồi đồng bộ với `Gdx.net.sendHttpRequest` trong LibGDX

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

trong mã này, biến id là không nhận được thiết lập vì saveUser chức năng đang trở lại ngay lập tức. Làm thế nào tôi có thể làm cho ứng dụng chờ kết quả của yêu cầu mạng để tôi có thể làm việc với các kết quả từ giao tiếp của máy chủ?

Đây là mã cho 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(); 
} 

Đây là lớp 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; 
    } 
} 
+1

'NetworkService' là gì? Nó không phải là một phần của Libgdx, mà tôi có thể thấy. Bất kỳ sự không đồng bộ nào bạn thấy là thuộc tính của mã bên trong 'saveUser', vì các phương thức Java luôn đồng bộ, vì vậy bạn sẽ cần phải mở rộng trên đó. –

+0

Xem chỉnh sửa mã. – Robbert

Trả lời

4

Các không đồng bộ của bạn đang nhìn thấy là từ Gdx.net.sendHttpRequest. Các phương thức trên tham số thứ hai (WerewolfsResponseListener) của bạn sẽ được gọi bất cứ khi nào yêu cầu quay lại. Phương thức thành công/thất bại sẽ không phải được gọi là "nội tuyến".

Có hai phương pháp cơ bản để xử lý cuộc gọi lại có cấu trúc như sau: "bỏ phiếu" hoặc "sự kiện".

Với cuộc bỏ phiếu, vòng lặp trò chơi chính của bạn có thể "kiểm tra" số responseListener để xem thành công hay thất bại của nó. (Bạn sẽ cần phải sửa đổi người nghe hiện tại của bạn một chút để phân biệt trường hợp thành công và chuỗi rỗng.) Khi bạn thấy một phản hồi hợp lệ, bạn có thể thực hiện user.setId() và như vậy.

Với "sự kiện" thì bạn có thể chỉ cần thực hiện cuộc gọi user.setId() bên trong cuộc gọi lại responseListener, vì vậy nó sẽ được thực hiện bất cứ khi nào mạng phản hồi. Đây là một chút phù hợp tự nhiên với API net Libgdx. (Điều đó có nghĩa là người nghe phản hồi của bạn sẽ cần tham chiếu đến đối tượng user.)

Không thể "chờ" nội tuyến để gọi lại mạng. API mạng Libgdx (chính xác) giả sử bạn không muốn chặn vô thời hạn trong chuỗi hiển thị của bạn, vì vậy nó không được cấu trúc cho điều đó (trình nghe sẽ được xếp hàng dưới dạng Runnable, vì vậy sớm nhất nó có thể chạy là cuộc gọi kết xuất tiếp theo) .

+0

OK. Sau đó tôi sẽ chỉ cập nhật đối tượng người dùng cục bộ khi hàm gọi lại của responseListener được gọi. Cảm ơn! – Robbert

1

Tôi không khuyến cáo điều này cho bất kỳ người nào, nhưng nếu bạn cần kiểm tra điều gì đó một cách nhanh chóng và dơ bẩn và hoàn toàn phải khối, điều này sẽ hoạt động. Không có thời gian chờ, do đó, một lần nữa, hãy chuẩn bị cho sự tuyệt đối bẩn thỉu:

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

} 
Các vấn đề liên quan