Question

I've got an AsyncTask class that will do a HttpGet-request. I want to do something after this AsyncTask is done, but from within my MainActivity.

Here is my TaskGetAPI class:

public class TaskGetAPI extends AsyncTask<String, Void, String>
{
    private TextView output;
    private Controller controller;

    public TaskGetAPI(TextView output){
        this.output = output;
    }

    @Override
    protected String doInBackground(String... urls){
        String response = "";
        for(String url : urls){
            HttpGet get = new HttpGet(url);
            try{
                // Send the GET-request
                HttpResponse execute = MainActivity.HttpClient.execute(get);

                // Get the response of the GET-request
                InputStream content = execute.getEntity().getContent();
                BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
                String s = "";
                while((s = buffer.readLine()) != null)
                    response += s;

                content.close();
                buffer.close();
            }
            catch(Exception ex){
                ex.printStackTrace();
            }
        }
        return response;
    }

    @Override
    protected void onPostExecute(String result){
        if(!Config.LOCALHOST)
            output.setText(result);
        else
            controller = Controller.fromJson(result);
    }

    public Controller getController(){
        return controller;
    }

And here is the method from my MainActivity where I use this class:

private void sendGetRequest(){
        ...

        // Web API GET-request
        if(!get_url.equals("") && get_url != null){
            TaskGetAPI task = new TaskGetAPI(output);
            task.execute(new String[] { get_url });

            // TODO: When AsyncTask is done, do:
            controller = task.getController();
            Log.i("CONTROLLER", controller.toString());
        }
    }

As you can see I set the Controller that I use later on in the onPostExecute-method of the AsyncTask.

Since this counters the entire purpose of Async tasks I first thought of removing the extends AsyncTask and just make a regular class & method of my HttpGet, but then I get a android.os.NetworkOnMainThreadException, meaning I need to use an AsyncTask (or something similar) to use HttpGet from within a different thread than my MainThread.

So, does anyone know what I should put at the // TODO?

I did try adding a boolean field (isDone) to the TaskGetAPI class with a getter and then use:

while(true){
    if(task.isDone()){
        Controller controller = task.getController();
        Log.i("CONTROLLER", controller.toString());
    }
}

But then the following steps occur:

  1. doInBackground of the TaskGetAPI class is completely done.
  2. Now we are stuck in this while(true)-loop..

and onPostExecute which sets the isDone to true is never called.

Was it helpful?

Solution

When the task will get finish then it will call onPostExecute, So you can use LocalBroadcast to send the broadcast message to main activity. You can use sendBroadcast which uses asynchronous manner i.e. send broadcast to all listener at a time rather than sendOrderedBroadcast.

OTHER TIPS

Assuming that you only use TaskGetAPI inside your Activity, you can just define TaskGetAPI as an inner class, like the example in https://developer.android.com/guide/components/processes-and-threads.html#AsyncTask

public class MainActivity extends Activity {

    public class TaskGetAPI extends AsyncTask<String, Void, String> {
        /*
         * This object is instanced inside the MainActivity instance,
         * so it has access to MainActivity methods and members
         * (including private ones).
         * Remember to only access to UI elements like views from the main thread,
         * that is, only from onPreExecute, onProgress or onPostExecute
         * In this class "this" makes reference to the TaskGetAPI instance,
         * if you need a refeence to the MainActivity instance, use MainActivity.this
         * 
         */

        protected String doInBackground(String... urls){ ... }

        protected void onPostExecute(String result){
            mMyTextView.setText(result);
        }
    }

    private TextView mMyTextView;
    public void onCreate(Bundle savedInstanceState) {

        setContentView(R.layout.main);
        mMyTextView = (TextView) findViewById(R.id.view);

        new TaskGetAPI().exec();
    }

}

If you need to use TaskGetAPI you can define it outside MainActivity and define a subclass as inner class of MainActivity.

There are other options, though, like defining listeners (like the onClickListeners) and call them in onPostExecute, but that is unnecesarily complex.

You can send a broadcast with your result from onPostExecute with the response. The activity will listen to it and execute the code you want.

while(true) is never a good idea, especially on mobiles where battery life is important.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top