Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does onPreExecute() and onPostExecute() execute on the UI thread or on the thread from which the AsyncTask has been started?

I have been writing AsyncTask's for short background operations in android for quite some time and had a very basic question. If I start an AsyncTask from a separate thread and not the main UI thread, would my onPreExecute()andonPostExecute methods be still called in the UI thread or the thread from which I started the AsyncTask. I am curious because I was unable to show a popup inside the onPreExecute() method when I started the it from some other thread.

EDIT 2

I tried writing this simple activity to try:

    public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        new Thread(new Runnable() {
            @Override
            public void run() {
                final TestAsyncTask task = new TestAsyncTask();
                task.execute();
            }
        }).start();
    }

    private class TestAsyncTask extends AsyncTask<Void, Void, Void> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected Void doInBackground(Void... voids) {
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            Toast.makeText(MainActivity.this, "Yo!", Toast.LENGTH_LONG).show();
        }
    }
}

This runs fine. But when I run the application with the following code:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        new Thread(new Runnable() {
            @Override
            public void run() {
                final TestAsyncTask task = new TestAsyncTask();
                task.execute();
            }
        }).start();
    }

    private class TestAsyncTask extends AsyncTask<Void, Void, Void> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            Toast.makeText(MainActivity.this, "Yo!", Toast.LENGTH_LONG).show();
        }

        @Override
        protected Void doInBackground(Void... voids) {
            return null;
        }
    }
}

It fails with the following error:

Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

as one of the lines in the stack trace.

like image 507
Swapnil Avatar asked Aug 23 '16 12:08

Swapnil


People also ask

Does onPostExecute run on UI thread?

Regarding your question: Yes, onPostExecute will still be called (because its invoked by a separate thread) even if your activity is destroyed and if the method will manipulate Views, you'll simply get Force Close error because reference to your activity is not available anymore.

When and on what thread does an AsyncTask's onPostExecute method run?

An asynchronous task is defined by a computation that runs on a background thread and whose result is published on the UI thread. An asynchronous task is defined by 3 generic types, called Params , Progress and Result , and 4 steps, called onPreExecute , doInBackground , onProgressUpdate and onPostExecute .

Which one of the following AsyncTask method is not executed on the UI thread?

This means that onPreExecute() is not executed on UI thread, but according to Android documentation: onPreExecute(), invoked on the UI thread before the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.

What method must be overridden when using AsyncTask to execute statements on a separate thread?

In Android, AsyncTask (Asynchronous Task) allows us to run the instruction in the background and then synchronize again with our main thread. This class will override at least one method i.e doInBackground(Params) and most often will override second method onPostExecute(Result).


3 Answers

While docs say that these callbacks execute in main thread - it is not true. onPreExecute() runs synchronously from the executeOnExecutor() i.e. in the thread that starts AsyncTask.

onPostExecute() is always runs in main thread. (it is invoked from finish(), and this happens inside Handler that uses looper of main thread).

like image 95
Sergio Avatar answered Sep 27 '22 21:09

Sergio


Quoting offical Docs:

onPostExecute
Added in API level 3
void onPostExecute (Result result)
Runs on the UI thread after doInBackground(Params...). The specified result is the value returned by doInBackground(Params...).


onPreExecute
Added in API level 3
void onPreExecute ()
Runs on the UI thread before doInBackground(Params...).

you can find it here https://developer.android.com/reference/android/os/AsyncTask.html#onPostExecute(Result)

Do in background runs on background thread while OnPreExecute and OnPostExecute run on main Ui thread.

like image 40
Saurabh Kataria Avatar answered Sep 27 '22 21:09

Saurabh Kataria


You should do UI updates and alert or pop up showing in AsyncTask's onPostExecute() method which runs on UI thread. The AsyncTask's doinBackground() method runs on another thread.

like image 35
Pavan Avatar answered Sep 27 '22 21:09

Pavan