Home » Android » java – Does onPreExecute() and onPostExecute() execute on the UI thread or on the thread from which the AsyncTask has been started?

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

Posted by: admin June 15, 2020 Leave a comment

Questions:

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.

How to&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).

Answer:

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.

Answer:

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.