为什么AsyncTask的postExecute方法不能在UI线程中运行?

时间:2012-03-15 17:36:01

标签: android android-asynctask

我有一个嵌套的内部类,它扩展了AsyncTask以在后台运行db查询。在post执行方法中,我调用父方法来更新像这样的视图

private class QueryRunner extends AsyncTask<Void,Void,Cursor> {

  @Override
  protected Cursor doInBackground(Void... voids)
  {
     return getContentResolver().query(LeadContentProvider.buildUri(app.getEntityId()),new String[]{LeadContentProvider._ID},null,null,LeadContentProvider.LEAD_STATUS_DATETIME +" desc");
  }

  @Override
  protected void onPostExecute(Cursor c)
  {
     onCursorLoaded(c);
  }
}

onCursorLoaded方法如下所示:

private void onCursorLoaded(Cursor c)
{
  mPagerAdapter = new LeadDetailsFragmentPagerAdaper(getSupportFragmentManager());
  mPager.setAdapter(mPagerAdapter);
  mPager.setCurrentItem(iIndex, false);
}

大部分时间这种方法都可以正常工作 - 但是有些用户在使用此堆栈跟踪时崩溃了:

java.lang.IllegalStateException: Must be called from main thread of process
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1392)
at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:431)
at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:139)
at android.support.v4.view.ViewPager.populate(ViewPager.java:804)
at android.support.v4.view.ViewPager.setAdapter(ViewPager.java:344)
at com.servicemagic.pros.activities.LeadDetails.onCursorLoaded(LeadDetails.java:205)
at com.servicemagic.pros.activities.LeadDetails.access$200(LeadDetails.java:25)
at com.servicemagic.pros.activities.LeadDetails$QueryRunner.onPostExecute(LeadDetails.java:196)
at com.servicemagic.pros.activities.LeadDetails$QueryRunner.onPostExecute(LeadDetails.java:170)
at android.os.AsyncTask.finish(AsyncTask.java:417)
at android.os.AsyncTask.access$300(AsyncTask.java:127)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:429)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:150)
at android.os.HandlerThread.run(HandlerThread.java:60)

那么 - 为什么没有在MainThread上调用postExecute()方法?

2 个答案:

答案 0 :(得分:2)

onPause() - onResume() loop没有通过onStart()。如果您需要在Activity的开头执行此操作,请将其放在onResume()中。你总是经历onResume()。

答案 1 :(得分:2)

我相信@hovanessyan所得到的是,假设AsyncTask在启动时与之交谈的片段可能与完成执行时的实例不同是不安全的。在AsyncTask运行时,Android可能会暂停甚至终止Fragment。这可以解释为什么这个问题是间歇性的。只有当用户的片段被暂停或销毁并重新创建时才会发生这种情况。

我们讨论了这个问题in this article。如果您阅读了文章中的第2和第3项,您将看到如何解决它。作为Fragment生命周期的一部分,您负责保存和恢复状态。请参阅Fragment lifecycle的Android文档。