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 aga
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]);
}
}
}
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());
}
}
}
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);
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.
Just like threads, AsyncTask
s can't be reused. You have to create a new instance every time you want to run one.
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.