3

I want to ensure that I don't slow down my app's startup time and need to start a background task that's unrelated to user input--for instance, filling a cache.

If I start an AsyncTask from my onCreate method, when will the doInBackground method actually begin to execute? (Assume a single core device)

Is it possible that Android could schedule it before onCreate/onResume has completed, or is it smart enough to recognize that the background thread shouldn't run until the UI thread is completely finished?

Jeff Axelrod
  • 27,676
  • 31
  • 147
  • 246

3 Answers3

1

If you look at AsyncTask source code you will see that it is just using ThreadPoolExecutor or serial executor for running tasks. Default internal behavior depends on Android version (from AsyncTask docs):

When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.

But anyway doInBackground execution is not connected with Activity lifecycle so AsyncTask may be executed at almost any time. This depends only on how many tasks you have already started, on default Executor which is used by AsyncTask and on thread scheduler.

Andrei Mankevich
  • 2,253
  • 16
  • 15
  • Good point: This is only valid for doInBackground() method if you're not sending anything to the UI. Normally is recommended to attach the context of some activity to show info of the task in onPreExecute() or onPostExecute() methods meanwhile doInBackround() is executing. So, for the most of the cases, there's a strong relation between AsyncTask and Activity. Only in a little few cases you could use it to not show anything of the backround task in the user's UI and in that cases only AsyncTask can be considered detached from Activities. – Martin Revert Jul 17 '12 at 03:16
0

I usually use AsyncTasks in onCreate() like this:

private MySuperSpecialTask mySuperSpecialTask;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // setContentView(...);
    // [...]

    mySuperSpecialTask = new MySuperSpecialTask();
    mySuperSpecialTask.execute();
}

@Override
protected void onDestroy() {
    super.onDestroy();
    if (mySuperSpecialTask != null) {
        mySuperSpecialTask.cancel(true);
    }
}

This makes sure that everything is initialized before the task gets started.

chrulri
  • 1,822
  • 14
  • 16
  • why your OnCreate method is not async void? Is there a problem doing it like that? – Emil Jul 05 '17 at 14:41
  • async void? Are you aware this is Java and not C#? Edit: Also, my answer is from 2012, so it may be obsolete for a while now. – chrulri Jul 18 '17 at 17:19
0

actually strictly speaking there is no execution order of your UI code and starting the asynctask I found out. Normally one does not experience this, however, if your UI thread takes longer for some reason, eg waiting for external input etc, the asynctask might have gotten started BEFORE UI code has finished.

Writing UI code is just a request to the Android system and this waits in the execution loop. So if asynctask starts before that because there are enough ressources (or as mentioned UI thread is delayed for whatever reason) there is no execution order guarantee.

One easy way to enforce this is - in case you don't mind and you can be sure that it is suffiencient - delay the starting of the asynctask with ScheduledExecutorService or a "cleaner" way would be to implement some kind of gate keeper that waits for a flag to be set to true and then start the asynctask. Or you may even have a while-loop at the beginning of your asynctask that waits for the flag to be set to true, like in many communication situations with external devices.

The flag would be set to true AFTER you can be (normally) sure that your UI has finished.

user387184
  • 10,953
  • 12
  • 77
  • 147