I'm facing a though problem regarding how to return the value of an async connection.
What I want to do is create a function (e.g. "getById") which interrogates a server and returns an object containing the answer of the server.
I tried with many different HTTP clients, but what I get is just the possibility to create local variable/interact with the UI, but not return the value.
The main architecture used in almost all the Http clients is: create a request, handle it with a request handler, and pass to it a response handler that will handle the response.
What happens is that I'm unable to access the response from the request handler, and neither detect when the request has finished in order to interact with the response; on the other side, from within the response handler, I can use the response to make UI changes or store it locally, but I can't return it to the user as a function result.
Is there any way to avoid this behaviour, or to bypass/crack it?
I tried mainly 4 ways:
- Use Futures & FutureTasks. Problem: I'm able to invoke them only on the request handler, and so I can't detect when the response is ready, but just when the request handler is ready.
- Use Callbacks. Problem: same as for Futures and FutureTasks.
- Use a while(true), checking if the response is ready. While this may work theoretically, practically it causes a block on the main thread, and so the app freezes, and will be stuck forever on the while (true), because it can't performe the code that would unlock it.
- Use Multithreading. This prevents blocking the main thread, but the problem is that a thread can't return a value, and the response handler can't access a lock used on another thread (or so it seems), so I'm unable to notify that the background task is finished.
Is there any way that I didn't consider, or anyone that maybe I implemented incorrectly?
Some sample code; in this code I'm using the Android-Async-Http client from Loopj, available here:
public JSONObject getById(String url, String id) {
JSONObject jo = null;
AsyncHttpClient client = new AsyncHttpClient();
final AsyncHttpResponseHandler ahrh = new AsyncHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
try {
jo = new JSONObject(new String(responseBody, "UTF-8"));
} catch (JSONException | UnsupportedEncodingException e) {
}
}
@Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
}
};
client.get(url + id, ahrh);
return jo;
}
This example fails because the value is returned before it available.