Why is the postExecute AsyncTask method not running on the UI thread?

I have a nested inner class that extends AsyncTask to run a db request in the background. In the post method post, I call the parent method to update the view like this:

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

      

The onCursorLoaded method looks like this:

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

      

This works fine in most cases, but some users encounter this stack trace:

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)

      

So - why isn't postExecute () method called on MainThread?

+3


source to share


2 answers


I believe what @hovanessyan does is that it is unsafe to assume that the fragment that AsyncTask accessed when it starts may not be the same as when it finishes executing. Android can pause or even complete the fragment while the AsyncTask is running. This explains why the problem is intermittent. This only happens to users when their fragment has been paused or destroyed and recreated.



This issue is discussed in this article . If you read points 2 and 3 in the article, you will see how to solve it. You are responsible for maintaining and restoring state as part of your chunk lifecycle. See Android documentation for Fragment Lifecycle .

+2


source


onPause () - The onResume () loop does not go through onStart (). If you need this to be executed at the start of your action, put it in onResume (). You are always looking at onResume ().



+2


source







All Articles