Why AsyncTask won't start if it starts / stops repeatedly?

So I was debugging an issue in my game where if I start then stop it a few times, I noticed that sometimes Asynctask doesn't seem to start, although I seem to be doing the right thing to start this. I've removed a lot of unnecessary code to show what's going on, but basically I can see that I'm going to start Asynctask, but the task never starts.

public void onStart()
{
    super.onStart();
    Log.d(TAG,"About to execute");
    Play_level.execute();
}

AsyncTask<Void,Integer,Integer> Play_level=new AsyncTask<Void, Integer, Integer>(){
     protected void onProgressUpdate(Integer ...time) {
            //Stuff goes in here.
     }
    @Override
    protected Integer doInBackground(Void... params) {
        Log.d(TAG,"In Task");
    }

};

      

And the logarithm shows:

03-10 19:28:16.983: D/Level(1535): About to execute
03-10 19:28:17.503: D/Level(1535): onStop()
03-10 19:28:17.993: D/Level(1535): onPause()
03-10 19:28:19.174: D/AJEG(1535): Starting Tongue
03-10 19:28:19.313: D/Level(1535): ImageList Previously Loaded
03-10 19:28:19.313: D/Level(1535): About to execute
03-10 19:28:19.853: D/Level(1535): onStop()
03-10 19:28:20.283: D/Level(1535): onPause()
03-10 19:28:21.464: D/AJEG(1535): Starting Tongue
03-10 19:28:21.604: D/Level(1535): ImageList Previously Loaded
03-10 19:28:21.604: D/Level(1535): About to execute
03-10 19:28:22.134: D/Level(1535): onStop()
03-10 19:28:22.404: D/Level(1535): onPause()
03-10 19:28:23.504: D/AJEG(1535): Starting Tongue
03-10 19:28:23.644: D/Level(1535): ImageList Previously Loaded
03-10 19:28:23.644: D/Level(1535): About to execute
03-10 19:28:24.184: D/Level(1535): onStop()

      

Also, no amount of re-entering the task seems to be able to restart the code, as the last bit of text shows.

To give a little more context, the starting language is reproduced in the onStart () of the parent activity (AJEG), the level is the name of the activity I'm launching. The ImageList command can be safely ignored, but I've included it for completeness. The part doInBackground

includes the text "Starting level _", where _ is the level that should be started. onStop () and onPause () are in a method showing when onStop()

and are onPause()

occurring in a level task.

+3


source to share


4 answers


So, the solution to the problem is indicated in this blog article :

AsyncTask uses a static internal work queue with a hard-coded limit of 10 items

So, essentially, I had an AsyncTask that never finished until 10, re-starting my thread. To get around this, I did the following:



  • I converted the AsyncTask to a class and ensured that only one instance works as swing suggested.
  • I canceled the task in the onStop () command as Mike D. suggested in his comment.
  • I made sure I check if ASyncTask is canceled in doInBackground

    .

The result looks something like this:

private LevelPlay Play_level;

public void onStop()
{
    super.onStop();
    Play_level.cancel(true);
}

public void onStart()
{
    super.onStart();
    Play_level=new LevelPlay();
    Play_level.execute();
}


class LevelPlay extends AsyncTask<Void, Integer, Integer>
{
     protected void onProgressUpdate(Integer ...time) {
     }
    @Override
    protected Integer doInBackground(Void... params) {
        Log.d(TAG,"In Task");
            Boolean keepRunning=true;
        while(keepRunning && !isCancelled ())
        {
                 //DoStuffHere
        }
     }
}

      

+5


source


From http://developer.android.com/reference/android/os/AsyncTask.html you notice: The task can be executed only once (an exception will be thrown if a second execution is attempted.)

.



In your application, you create a single AsyncTask and try to reuse it. Instead, create a new instance for each run.

+3


source


Here is the code that works for me:

public class ImageActivity extends Activity {

    private Thread worker;

    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.main);

        worker = new Thread(new Runnable(){

            private void updateUI(final List<Object> list)
            {
                if(worker.isInterrupted()){
                    return;
                }
                runOnUiThread(new Runnable(){

                    @Override
                    public void run()
                    {
                        // Update view and remove loading spinner etc...
                    }
                });
            }

            private List<Object> download()
            {
                // Simulate download
                SystemClock.sleep(1000);
                return new ArrayList<Object>();
            }

            @Override
            public void run()
            {
                Log.d(TAG, "Thread run()");
                updateUI(download());
            }

        });
        worker.start(); }

    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        worker.interrupt();
    }
}

      

And Restriction on AsyncTask

Hope it helps.

+3


source


Assuming you are talking about a onStart()

method Activity

, it might be because your application was not removed from memory when you returned to it, which means your method onStart()

is probably not being called. You might want to consider using onResume()

either onRestart()

(or perhaps both), and perhaps reverse AsyncTask

the onPause()

. This also means that in the background task, you have to check if it was canceled.

See Mach's answer for why this is happening.

Activation life cycle .

AsyncTask .

+1


source







All Articles