1

The problem is that i cant get the JSON result from my doInBackground. I know i need a handler and work with onPostExecute, but i cant make it work. I have a controller whos in charge of making the conection extending from AsyncTask. I call that controller.execute() on the main thread and it gives me an AsyncTask object instead of the JSON. This is the controller:

final MediaType JSON
        = MediaType.parse("application/json; charset=utf-8");

@Override
protected String doInBackground(String... params){
    try {
        JSONObject newJson = new JSONObject(params.toString());

        String dirArchivo =  "http://10.0.2.2/SoulStoreProject/"+newJson.get("dir");

        OkHttpClient client = new OkHttpClient();

        RequestBody body = RequestBody.create(JSON, newJson.toString());
        Request request = new Request.Builder()
            .url(dirArchivo)
            .post(body)
            .build();
        Response response = client.newCall(request).execute();
        return response.body().string();
    } catch (IOException e) {
        return e.getMessage().toString();
    } catch (JSONException e) {
        return e.getMessage().toString();
    }
}

and this is the main class:

JSONObject requestObject = new JSONObject();
     requestObject.put("nick", txtNicklog.getText().toString());
     requestObject.put("password", txtPasslog.getText().toString());
     requestObject.put("dir", "devolverJugador.php");

String result = Controller.execute(requestObject);

JSONObject resultFromAsyncTask= new JSONObject(result);

i dont know where to write the handler and how to call it from onPostExecute. Or if there is another way to solve it im open to sugestions

2 Answers2

1

The problem here is about understanding how asynchronous tasks work. When you are calling Controller.execute(requestObject), it will run in background thread (off the main thread) and control will pass to the next line.

And thus, by the time control reaches JSONObject resultFromAsyncTask= new JSONObject(result);, your response is NOT yet fetched.

Along with that, I don't know how are you able to compile this:

String result = Controller.execute(requestObject);

Anyway, I would recommend you not to use AsyncTask and instead use OkHttp's asynchronous call to make the network requests.

OkHttpClient client = new OkHttpClient();

RequestBody body = RequestBody.create(JSON, newJson.toString());
Request request = new Request.Builder()
            .url(dirArchivo)
            .post(body)
            .build();
client.newCall(request).enqueue(new Callback() {
      @Override
      public void onFailure(Call call, IOException e) {
           e.printStackTrace();
      }

      @Override
      public void onResponse(Call call, final Response response) throws IOException {
           if(resonse.isSuccessful(){
                //Running on UI thread, because response received is NOT on UI thread.
                new Handler(Looper.getMainLooper()).post(new Runnable() {
                   @Override
                   public void run() {
                      //use response to update any UI component
                   }
                });
           }
        }
    });

NOTE: I have assumed that you are using latest version of OkHttp i.e., 3.2.0

Rohit Arya
  • 6,751
  • 1
  • 26
  • 40
  • I don't think you need the `new Handler` piece to run on the main thread. The callback is returned to the correct place, but if you did need the handler, then `response` should be made `final` in the parameter. – OneCricketeer Apr 22 '16 at 20:31
  • @cricket_007, I have changed the `Response` to `final`, thanks for pointing it out. But I don't agree to your first point. OkHttp doesn't know anything about main thread and `onResponse` [runs on background thread](http://stackoverflow.com/a/24248963/2720553). – Rohit Arya Apr 22 '16 at 20:36
  • I typically stick to Volley, so I may be wrong, but I did find this [sample code for asynchronous GET](https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/AsynchronousGet.java) from Square's Github – OneCricketeer Apr 22 '16 at 21:00
  • the problem is that i need the controller to be universal, i need to use it very often so i cant update the UI component there, that's why i use a variable on the Main. And i cant compile that, that's the problem cuz that return an AsyncTask object, and i need a String or a Json object., But i like the idea of using okhttp thanks – Martin Chocho Apr 22 '16 at 21:51
  • @MartinChocho,you use this as a universal function, get the data using an `interface` – Rohit Arya Apr 22 '16 at 21:58
  • @MartinChocho, that's great. :) – Rohit Arya Apr 24 '16 at 05:31
1

The method execute() of an AsyncTask instance will not return to you the json start the assyncrhonous execution. So, this line String result = Controller.execute(requestObject); will not wait until the AsynTask be finished to return the json to result variable, the asynctask is running in a second thread.

If you want to stop everything and wait the asynctask be finished, you have to call the method get: String result = Controller.execute(requestObject).get();. But, have in mind that you will freeze your UI and it's not good! The best approach is run the AsynTask assynchrously and deal with the json in the method onPostExecute().

Tássio Auad
  • 111
  • 5