I have an activity which, during its execution, kicks off a couple of AsyncTasks and a couple of Threads.
If these continue when the activity is destroyed/recreated then all sorts of errors occur so my bright idea was to make each non UI thread register itself, adding itself to an ArrayList<Thread>() and ArrayList<AsyncTask>() meaning that I could, onDestroy(), iterate through these ArrayLists and destroy them like so:
@Override
public void onDestroy()
{
for(AsyncTask task : tasks)
task.cancel(true);*
for(Thread thread : threads)
thread.interrupt();
}
Unfortunately this throws a java.util.ConcurrentModificationException on the line marked with *. I tried wrapping each for loop in a synchronize block to make sure the ArrayLists aren’t being modified by any other Threads.
Do AsyncTasks destroy themselves on completion (and therefore throw the above error)?
Does anyone know of a better way of controlling Threads in an Android environment?
EDIT
Changing the code to use for(int i =0 : i < array.size() ; i++) seems to solve this problem but I would still like to know /why/ it happens:
synchronized(tasks)
{
for(int i=0; i < tasks.size(); i++)
tasks.get(i).cancel(true);
}
synchronized(threads)
{
for(int i=0; i < threads.size(); i++)
threads.get(i).interrupt();
}
As far as I can tell, AsyncTasks disappear, once they’ve run the onPostExecute and you’ve set the instance to null, or something similar. What are you doing in a Thread that you couldn’t do in a Service or AsyncTask? Are you doing UI operations in your threads (like, runOnUIThread or something) that would cause these threads to error when the app isn’t in foreground?
The nice thing about doing things in a Service, is you can broadcast that you’re about to close the app, and stop any actions in the Service that you no longer need running, essentially hibernating the Service until you fire it up again when the app comes into foreground.