0

An AsyncTask is executed on click:

List<RSSItem> list = new Vector<RSSItem>();
private OnClickListener click = new OnClickListener() {
    public void onClick(View view) {
        list.clear();
        if((dft.getStatus().toString()).equals("RUNNING")) dft.cancel(true);
        currentCategory = catigoriesHolder.indexOfChild(view);
        dft = new DownloadFilesTask();
        dft.execute(rssFeedURL[currentCategory]);
    }
};

In doInBackGround method the variable list is filled up. How to prevent the list to be cleared at point at which it is used to fill ListView. How to be sure, that on next click the previous instance of AsyncTask have been destroyed and there is no further processing of it.

The issue is regarding version 1.6.

nenito
  • 1,214
  • 6
  • 19
  • 33
  • See this question: http://stackoverflow.com/questions/9893813/can-an-android-asynctask-doinbackground-be-synchronized-to-serialize-the-task-ex – Lorenzo Polidori Mar 29 '12 at 07:29

2 Answers2

3

First of all async task's in general don't run at the same moment, but the execution of the same async task is actually a queue. so imagine if you create 2 instances of your DownloadFilesTask and execute them in the same method like:

task1.execute();
task2.execute();

this means that task 2 wont be run until task1 has finished the whole onPreExecute,DoInBg,onPostExecute process so you can be sure that that won't happen simultaniously. also the taskStatus is an ENUM. you can check it as such not as a string like:

task.getStatus()==Status.FINISHED

in your case if you don't want to queue multiple tasks until the currently running one is complete then do something like this:

if(task==null || task.getStatus()!=Status.FINISHED){
    task = new DownloadFilesTask();
    task.execute();
}

Canceling a task means that the doInBackground will run but postExecute wont. you can check if the task isRunning in order to cancel it during bg processing somewhere also.

DArkO
  • 15,880
  • 12
  • 60
  • 88
  • 1
    This actually is not documented. On Android 1.5 all async tasks were queued, on Android 1.6+ several `AsyncTask`s could run in parallel. There are plans to restore "sequential" execution of `AsyncTask`s in further releases of Android. But since this is not yet documented, nobody should rely on this behavior. (http://groups.google.com/group/android-developers/msg/3deeb36dccb4e9a5) – inazaruk Aug 10 '11 at 12:57
  • Do I have to understand that the way I'm doing it is wrong and it'll generated an error. I got what you mean and fully understood it! But this will block if I click on new category, I mean, I'm clicking on different link(button) and nothing happens until the current instance of **task** is completed. It is secured, but if the user network connection is slow it will take a few seconds to finish it. Is there other way to interrupt the current task, else I'll implemented that way and consider your answer to be correct! – nenito Aug 10 '11 at 13:03
  • Well the only way is to check the status during the async task. you can use Threads. Those are ran in parallel, they are a bit heavier, but still will do the job you want. also there is a project from CommonsWare that allows a couple of tasks to be ran at the same time. Look for AsyncTaskEx: http://code.google.com/p/alldroid/source/browse/trunk/AllDroid/src/com/commonsware/cwac/task/AsyncTaskEx.java?spec=svn24&r=24 – DArkO Aug 10 '11 at 14:23
2

You can store reference to AsyncTask in member variable. So your code would look like this:

List<RSSItem> list = new Vector<RSSItem>();
DownloadFilesTask downloadTask = null;

private OnClickListener click = new OnClickListener() {
    public void onClick(View view) {
        list.clear();
        if((dft.getStatus().toString()).equals("RUNNING")) dft.cancel(true);
        currentCategory = catigoriesHolder.indexOfChild(view);

        if(downloadTask == null){
           downloadTask = new DownloadFilesTask();
           downloadTask.execute(rssFeedURL[currentCategory]);
        } else { 
           //show warning here
        }
    }
}

Of course, you'll need to set downloadTask to null in onPostExecute() for this to work.


As an added benefit you now can cancel outstanding task if Activity is being destroyed:

 @Override
 onDestroy() {
     if(downloadTask != null) {
         downloadTask.cancel();
     }
 }

Which you should do anyway.

inazaruk
  • 74,247
  • 24
  • 188
  • 156
  • It is stored as a member, I just did not share that part of source. The null checking is also done. Thanks for `@Override onDestroy()` it is really useful. – nenito Aug 10 '11 at 13:06