Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android : can AsyncTask return in another thread than UI thread?

Android documentation says that AsyncTask postExecute() is called on the UI thread. I was under the impression that postExecute() was called from the Thread where execute() was called : I have been using an AsyncTask in a background Service with its own thread, and postExecute() was called in the service thread, not the main thread.
However, I recently had an issue with the postExecute() not being called at all, while an exception was thrown : " sending a message to a Handler on a dead thread".

How is it exactly :
- shall AsyncTask be used ONLY from the main thread ?
- if not, in which thread postExecute() is supposed to be called : always the UI thread, or the execute() calling thread ?

Thank you

like image 207
user244129 Avatar asked Jul 21 '10 15:07

user244129


2 Answers

AsyncTask's pre and postExecute methods are invoked on the thread on which the task instance was created. Where you call execute() doesn't matter. The thread on which you create the task must be a looper thread and in practice should always be the main thread (or UI thread.)

like image 60
Romain Guy Avatar answered Sep 24 '22 21:09

Romain Guy


It seems that you can start AsyncTask from somewhere else than the main Thread but the postExecute is really executed on the main thread. Here is my test, tell me if it seems logical to you :

public class AsyncLoader extends AsyncTask<Context, String, Boolean> {
private ConnectivityManager cm;
private ArrayList<Contact> nameList;
private Context ctx;
private static int i = 0;

@Override
protected Boolean doInBackground(Context... params) {
    ctx = params[0];
    cm = (ConnectivityManager) params[0].getSystemService(Activity.CONNECTIVITY_SERVICE);
    if (i < 3) {
        i++;
        new AsyncLoader().execute(ctx);
        System.out.println("Thread name (from doInBackground) : " + Thread.currentThread().getName());
        System.out.println("compteur async " + i);
    }
    if (cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isAvailable()) {
        nameList = (ArrayList<Contact>) ContactLoaderXml.loadContactsData(); //this is a loading from the web + sax parser
        return true;
    } else {
        return false;
    }
}
@Override
protected void onPostExecute(Boolean result) {
    super.onPostExecute(result);
    System.out.println("Thread name (from postexecute) : " +  Thread.currentThread().getName());
}
}

Here is the stacktrace after the tasks :

I/System.out(  641): Thread name (from doInBackground) : AsyncTask #1  
I/System.out(  641): compteur async 1  
I/System.out(  641): Thread name (from doInBackground) : AsyncTask #2  
I/System.out(  641): compteur async 2  
I/System.out(  641): Thread name (from doInBackground) : AsyncTask #3  
I/System.out(  641): compteur async 3  
I/System.out(  641): Thread name (from postexecute) : main  
I/System.out(  641): Thread name (from postexecute) : main  
I/System.out(  641): Thread name (from postexecute) : main  
I/System.out(  641): Thread name (from postexecute) : main 

I don't know why the post execute is done 4 times though...

like image 34
Sephy Avatar answered Sep 22 '22 21:09

Sephy