【问题标题】:Android : can AsyncTask return in another thread than UI thread?Android:AsyncTask 可以在 UI 线程之外的另一个线程中返回吗?
【发布时间】:2010-07-21 15:20:56
【问题描述】:

Android 文档说 AsyncTask postExecute() 在 UI 线程上被调用。我的印象是postExecute() 是从调用execute() 的线程中调用的:我一直在具有自己线程的后台服务中使用 AsyncTask,并且在服务线程中调用了 postExecute(),而不是在主线程中调用线程。
但是,我最近遇到了一个根本没有调用 postExecute() 的问题,同时引发了异常:“向死线程上的处理程序发送消息”。

具体怎么样:
- AsyncTask 是否只能在主线程中使用?
- 如果不是,应该在哪个线程中调用 postExecute():总是 UI 线程,还是 execute() 调用线程?

谢谢

【问题讨论】:

  • 文档 appears 也误导了我,虽然我没有遇到异常,但我的经验是在外部使用 AsyncTask UI 线程 onPostExecute 来自调用线程,不一定是 UI 线程(如果需要操作 UI,则需要 Handler)。

标签: android multithreading android-asynctask


【解决方案1】:

在创建任务实例的线程上调用 AsyncTask 的 pre 和 postExecute 方法。在哪里调用 execute() 并不重要。您创建任务的线程必须是 Looper 线程,并且在实践中应该始终是主线程(或 UI 线程)。

【讨论】:

  • 感谢您的具体回答!
  • 在 4.1+ 中仍然是这种情况吗?我已经在处理程序线程中启动了异步任务,但结果仍在主线程上。
  • 如果你在不同的线程上创建了一个监听器呢?如果你调用它,它还会在它创建的线程上触发吗?
【解决方案2】:

似乎您可以从主线程以外的其他地方启动 AsyncTask,但 postExecute 确实在主线程上执行。 这是我的测试,告诉我这对你来说是否合乎逻辑:

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());
}
}

这是任务之后的堆栈跟踪:

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 

我不知道为什么 post 执行会执行 4 次...

【讨论】:

  • 我猜是因为你在你的对象上调用了execute来进入第一个doInBackground,所以onPostexecute被调用了4次。我不确定将任务的创建嵌套在 doInBackground 中是否是一个好主意......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-15
  • 1970-01-01
  • 2013-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-17
相关资源
最近更新 更多