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

3

11

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.

Niles answered 23/8, 2016 at 12:52 Comment(1)
calling AssynTask in Activity or Class?Zoara
D
16

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).

Dulci answered 23/8, 2016 at 13:9 Comment(3)
I tried making a Toastmessage from both onPreExecute() and onPostExecute() (I edited the question to include the code). It fails in both the cases.Niles
@Niles Actually your code throws toast from doInBackground(). Are you sure that toast from onPostExecute() crashes app?Dulci
Anybody knows how to communicate this to the Android team so that we can have this on the documentation as well?Niles
L
4

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.

Lew answered 23/8, 2016 at 12:57 Comment(0)
A
1

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.

Allyn answered 23/8, 2016 at 13:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.