-2

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:

  1. 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.
  2. Use Callbacks. Problem: same as for Futures and FutureTasks.
  3. 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.
  4. 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.

ThomasThiebaud
  • 11,331
  • 6
  • 54
  • 77
tenik
  • 250
  • 1
  • 4
  • 20
  • 3
    You have it already, its called AsyncTask class, and it handles all. – Nanoc Nov 13 '15 at 11:51
  • http://developer.android.com/reference/android/os/AsyncTask.html – Fildor Nov 13 '15 at 11:52
  • How would you use an AsyncTask to improve that code? In my opinion, if you include it in an AsyncTask, you will face the same problem, but inside that class, because you will still need a way to communicate that the response is ready – tenik Nov 13 '15 at 11:52
  • Well, you would need to block the method until the value is set (definitely not recommended!) or do it with a callback. – mad_manny Nov 13 '15 at 12:07
  • I have showed you how can you block or make wait for response to come and your saying thats just adding another stack. – Pankaj Nov 13 '15 at 12:39
  • I managed to do it with AsyncTask. If any of you wants to answer with that, I will choose it and close the question – tenik Nov 13 '15 at 14:32

1 Answers1

1

Have you tried with an asyncTask? It is used to perform operation in background avoiding UI freezing. You need to extend the AsyncTask class, override the doInBackground method in which you do the Http request and the onPostExecute method to update the UI on the main thread.

Take a look here

Community
  • 1
  • 1
Marco
  • 705
  • 8
  • 28