19

I have an application and because you can't do network operations on the main thread I'm using AsyncTask, so the question is once I execute() the AsyncTask and right after that I finish() the activity, and maybe the user will finish() the whole app, so what I'm wondering is:

  1. Will AsyncTask always finish doInBackground() and onPostExecute() even if the app is closed as long as execute() was called when the app was running?
Akeshwar Jha
  • 4,516
  • 8
  • 52
  • 91
JRowan
  • 6,824
  • 8
  • 40
  • 59
  • 4
    You should use your activity life-cycle to cancel running task, using `cancel` method of Asynctask. It is useless to continue network operation which is most likely continue to run even your UI is destroyed. However after completion of network operation when it will try to update your UI app will run into issue. – minhaz Apr 25 '13 at 01:10

5 Answers5

15

You will be able to test this. And yes It does. If execute was called you can see Asynctask will still execute UNLESS it does something to the forground or UI related. (it may cause launcher to crash).


However, if it was close by the system. It may or may not continue executing the method. I have already tested and answered here. Reply to comment: Tested:

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        new Worker().execute();
    }
private class Worker extends AsyncTask<Void, Void, String> {

    @Override
    protected String doInBackground(Void... arg0) {
        Log.i("SomeTag",
                "start do in background at " + System.currentTimeMillis());
        String data = null;

        try {
            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(
                    "https://stackoverflow.com/questions/tagged/android");

            HttpResponse httpResponse = httpClient.execute(httpGet);
            HttpEntity httpEntity = httpResponse.getEntity();
            data = EntityUtils.toString(httpEntity);
            Log.i("SomeTag",
                    "doInBackGround done at " + System.currentTimeMillis());
        } catch (Exception e) {
        }
        return data;
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        Log.i("SomeTag", System.currentTimeMillis() / 1000L
                + " post execute \n" + result);
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();
    Log.i("SomeTag", System.currentTimeMillis() / 1000L + "  onDestory()");
}

04-24 21:42:57.981: I/SomeTag(5961): start do in background at 1366854177994
04-24 21:43:00.974: I/SomeTag(5961): 1366854180  onDestory()
04-24 21:43:02.946: I/SomeTag(5961): doInBackGround done at 1366854182946
04-24 21:43:02.946: I/SomeTag(5961): 1366854182 post execute 
04-24 21:43:02.946: I/SomeTag(5961): <!DOCTYPE html>
04-24 21:43:02.946: I/SomeTag(5961): <html>
04-24 21:43:02.946: I/SomeTag(5961): <head>
04-24 21:43:02.946: I/SomeTag(5961):         
04-24 21:43:02.946: I/SomeTag(5961):     <title>Newest &#39;android&#39; Questions - Stack Overflow</title>
04-24 21:43:02.946: I/SomeTag(5961):     <link rel="shortcut icon" href="http://cdn.sstatic.net/stackoverflow/img/favicon.ico">
//....
Community
  • 1
  • 1
wtsang02
  • 18,603
  • 10
  • 49
  • 67
  • thanks thats exactly what i was wondering, from what you stated i have to go and make some changes, trying to get it right the first time you know, thanks for your time – JRowan Apr 25 '13 at 01:10
  • I have to disagree a bit here. AsyncTasks are **suppose** to be UI-related. The `onPostExecute()` is **always** ran from the UI thread, so it will never be called in that case. – ddmps Apr 25 '13 at 01:13
  • @Pescis Updated and tested. Please point out my error if you find my test to be inaccuracy. – wtsang02 Apr 25 '13 at 01:45
  • 2
    Apparently the UI-thread can still run after `onDestroy()` - wasn't expecting that. So it's probably a very good idea to cancel any UI-Tasks to free up resources. – ddmps Apr 25 '13 at 02:25
9

onPostExecute() is called from the UI thread - so if the UI thread is no longer running, it will not continue to run. However doInBackGround() is ran from a separate worker thread so it will keep on until done (or if the JVM process is killed by the OS, which is also a possibility). Note that AsyncTasks are only recommended for shorter UI-bound background tasks and not long-running background work (a few seconds).

In short, you can not assume that it will keep on and definitely not assume that it will post its progress or call onPostExecute().

ddmps
  • 4,350
  • 1
  • 19
  • 34
6

When you call finish() on Activity, the Activity is destroyed, but the main thread is not. [NOTE: Activity runs on Main Thread. Activity is not Main Thread. ]

So, doInBackground() on background thread and onPostExecute() on main thread will be executed. However, if onPostExecute() does any UI-related tasks, you will get ANR because there is no UI at this point. For eg, if you just print a Log.d() statement inside onPostExecute(), the statement will be visible in Logcat.

** These will be possible only if the process is alive, & is not killed by Android Low Memory Killer.

Ashok Bijoy Debnath
  • 1,493
  • 1
  • 17
  • 27
1

See the image to see which methods are executed in which thread.

enter image description here

Arun
  • 613
  • 1
  • 7
  • 14
1

You can easily test this, just make doInBackground() last longer, for example add Thread.sleep(5000) and then try various scenarios :

  • If you finish the Activity that started the AsyncTask, or navigate away from it, AsyncTask finishes normaly, but then you'll probably cause a memory leak or crash your app in onPostExecute() if you hold a reference to the surrounding Activity (like a UI element), that is not "alive" any more.
  • If you minimize your app by pressing "home" button, it will again complete normally, but can crash the app in onPostExecute()
  • If you kill your app process (or the system does that), it will terminate your AsyncTask and the job you wanted it to do doInBackground() will not be done. The same goes if you simply start the thread using new Thread(new Runnable() {...
Alexandar
  • 235
  • 3
  • 8