How to run the same asynctask more than once?

Android

Android Problem Overview


I have my asyncTask run when the activity first starts, then if network connectivity is not available then i have a refresh button that tries to run the asyncTask to try again. But i get a debug error saying this..

07-29 18:14:21.290: ERROR/AndroidRuntime(9080): FATAL EXCEPTION: main
07-29 18:14:21.290: ERROR/AndroidRuntime(9080): java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once)
   07-29 18:14:21.290: ERROR/AndroidRuntime(9080):     at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:541)
   07-29 18:14:21.290: ERROR/AndroidRuntime(9080):     at android.os.AsyncTask.execute(AsyncTask.java:499)
  07-29 18:14:21.290: ERROR/AndroidRuntime(9080):     at com.fttech.gameIT.MainMenu$1.onClick(MainMenu.java:90)

Is there anyway to run this twice?

Android Solutions


Solution 1 - Android

Just create another instance and execute it.

Solution 2 - Android

Just like threads, AsyncTasks can't be reused. You have to create a new instance every time you want to run one.

Solution 3 - Android

You can never execute a thread again, not in Java, not in any other language, once the thread is done with the run() method, you cannot restart it, which is why you are getting the IllegalStateException.

You can however still call the methods on that thread but they will run on the thread that is calling them NOT on a different thread. Therefore you will have to create a new one.

Solution 4 - Android

You cannot run same instance of an AsyncTask more than once. Let's assume you have an AsyncTask named MyAsyncTaks and you intend to do something like this,

	MyAsyncTask myAsyncTask = new MyAsyncTaks();
	myAsyncTask.execute(); // Works as expected
	.
	.
	.
	.
	myAsyncTask.execute(); // This will throw you exception
	

The reason for this is, a thread once finishes its 'run' method, cannot be assigned another task. Here, on the first invocation of execute(), your AsyncTask started running and after doing its job, the thread comes out of run. Naturally, next invocation of execute() will throw you exception.

The simplest way to run this more than once is to create a new instance of MyAsyncTaks and call execute on that.

	MyAsyncTask myAsyncTask = new MyAsyncTaks();
	myAsyncTask.execute(); // Works as expected
	.
	.
	.
	MyAsyncTask myAsyncTask2 = new MyAsyncTaks();
	myAsyncTask2.execute(); // Works as expected
	

Though its not needed to be mentioned here, one must be aware that post Android SDK version Honeycomb, if your run more than one AsyncTask at once, they actually run sequentially. If you want to run them parallally, use executeOnExecutor instead.

Solution 5 - Android

Just make a new call like new asyncTask().execute(); You must create a new object to restart that task.

Solution 6 - Android

I just create the asynctask then create a runnable that creates new instances of the asynctask. Then you can submit your runnable over and over again to the handler.

class MyAsyncTask extends AsyncTask<String, Void, String>{ ...}

Runnable myRunner = new Runnable(){
     public void run() {
        new MyAsyncTask ().execute(...);
}};
myHandler.post(myRunner);

Solution 7 - Android

This solved my problem:

public class MainActivity extends AnimationActivity {
	
	MyAsyncTasks asyncTasks = new MyAsyncTasks();
	
	@BindView(R.id.refresh_btn)
    Button refreshBtn;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
        setUnbinder(ButterKnife.bind(this));  // ButterKnife usage
		
		syncTasks();  // run asyncTasks on activity start
		
		refreshBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                syncTasks(); // run asyncTasks on button click
            }
        });
	}
	
	private void syncTasks() {
        try {
            if (asyncTasks.getStatus() != AsyncTask.Status.RUNNING){   // check if asyncTasks is running
                asyncTasks.cancel(true); // asyncTasks not running => cancel it
                asyncTasks = new MyAsyncTasks(); // reset task
                asyncTasks.execute(); // execute new task (the same task)
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("MainActivity_TSK", "Error: "+e.toString());
        }
    }
}

Solution 8 - Android

You can do it like this :

private MyAsyncTask createAsyncTask(){
    if (myAsyncTask == null){
        return myAsyncTask = new MyAsyncTask();
    }
        myAsyncTask.cancel(true);
        return myAsyncTask = new MyAsyncTask();
 }

and then you can use it :

createAsyncTask().execute();

this make a new instance of your background task everytime.

Solution 9 - Android

Async tsk only run once as the Exceptions says the task has already been executed.. So you just have to make a new instance of async and then call .execute(); in order to run it again .. thank you

Solution 10 - Android

I created an Arraylist of type ProgressUpdater(Name of class which extends AsyncTask) and added the instances into it(in the onClick of a button). So you can execute and cancel these task when needed.

public class MainActivity extends Activity {
ProgressBar progress;
ProgressUpdater task;
ArrayList<ProgressUpdater> pu = new ArrayList<MainActivity.ProgressUpdater>();
int count = 0;

@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
	progress = (ProgressBar) findViewById(R.id.progress);

}

public void onClick(View v) {
	switch (v.getId()) {
	case R.id.btn:
		task = new ProgressUpdater();
		pu.add(task);
		count++;
		pu.get(count - 1).execute(0);
		System.out.println("task" + task);

		// task.execute(10);
		break;
	case R.id.btnCancel:
		if (count >= 0) {
			pu.get(count - 1).cancel(true);
			pu.remove(count - 1);
			count--;
		}
		// task.cancel(true);

		break;

	}
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
	// Inflate the menu; this adds items to the action bar if it is present.
	getMenuInflater().inflate(R.menu.main, menu);
	return true;
}

private class ProgressUpdater extends AsyncTask<Integer, Integer, Void> {
	@Override
	protected void onPreExecute() {
		// TODO Auto-generated method stub
		super.onPreExecute();
		progress = (ProgressBar) findViewById(R.id.progress);
		progress.setMax(100);
	}

	@Override
	protected Void doInBackground(Integer... params) {
		// TODO Auto-generated method stub
		int start = params[0];
		for (int i = start; i <= 100; i++) {
			try {
				boolean cancelled = isCancelled();
				if (!cancelled) {
					publishProgress(i);
					SystemClock.sleep(100);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	@Override
	protected void onPostExecute(Void result) {
		// TODO Auto-generated method stub
		super.onPostExecute(result);
		Log.v("Progress", "Finished");
	}

	@Override
	protected void onCancelled() {
		// TODO Auto-generated method stub
		super.onCancelled();
		progress.setMax(0);

	}

	@Override
	protected void onProgressUpdate(Integer... values) {
		// TODO Auto-generated method stub
		super.onProgressUpdate(values);
		progress.setProgress(values[0]);
	}

}

}

Solution 11 - Android

in your MainActivity you can put so this:

LeoAsyncTask leoAsyncTaskGeneric;


public void onClick_AsyncTask(View view) {

    LeoAsyncTask leoAsyncTaskInner = new LeoAsyncTask();
    leoAsyncTaskInner.execute();

    leoAsyncTaskGeneric=leoAsyncTaskInner; 

}

/**if you create a space in memory of your AsyncTask class as a generic, then you can create an instance of that same class within the onClick method, and there the equals, so every time you press onClick you will be using a new instance of the Class AsyncTask, it will not give you problems */

Solution 12 - Android

You could cancel your asyncTask when you press the button and then execute it again.

Inside OnClic method:

asyncTask.cancel();
AsyncTask asyncTask = new AsyncTask();
asyncTask.execute();

Solution 13 - Android

@coder_For_Life22 I think am late for the answer ,anyway you can do like

    @Override
    protected void onPostExecute(Void a) {
       
        myAsyncTask=new MyAsyncTask();
    }

in order to start a new AsyncTask after execution :)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questioncoder_For_Life22View Question on Stackoverflow
Solution 1 - AndroidCristianView Answer on Stackoverflow
Solution 2 - AndroidRagunath JawaharView Answer on Stackoverflow
Solution 3 - AndroidOscar GomezView Answer on Stackoverflow
Solution 4 - AndroidKapsView Answer on Stackoverflow
Solution 5 - AndroidBobbake4View Answer on Stackoverflow
Solution 6 - AndroidoneporterView Answer on Stackoverflow
Solution 7 - AndroidCamerevView Answer on Stackoverflow
Solution 8 - AndroidAhmed MohamedView Answer on Stackoverflow
Solution 9 - AndroidFakhar UllahView Answer on Stackoverflow
Solution 10 - AndroidAkhil SomanView Answer on Stackoverflow
Solution 11 - AndroidLeonardoView Answer on Stackoverflow
Solution 12 - AndroidAdrian TrilloView Answer on Stackoverflow
Solution 13 - AndroidJustin ImranView Answer on Stackoverflow