2011-08-10 4 views
0

Un AsyncTask est exécuté sur un clic:exécution parallèle de AsyncTask

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]); 
    } 
}; 

Dans doInBackGround méthode est rempli la variable liste up. Comment empêcher la liste d'être effacée au point auquel elle est utilisée pour remplir ListView. Comment être sûr, que lors du prochain clic, l'instance précédente de AsyncTask a été détruite et il n'y a pas d'autre traitement de celui-ci.

Le problème concerne la version 1.6.

+0

Voir cette question: http://stackoverflow.com/questions/9893813/can-an-android-asynctask-doinbackground-be-synchronized-to-serialize-the-task-ex –

Répondre

3

Tout d'abord les tâches asynchrones ne s'exécutent pas en général au même moment, mais l'exécution de la même tâche asynchrone est en réalité une file d'attente. alors imaginez si vous créez 2 instances de votre DownloadFilesTask et de les exécuter dans la même méthode comme:

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

cela signifie que la tâche 2 être exécuté habitude jusqu'à ce que Task1 a terminé l'ensemble OnPreExecute, DoInBg, processus onPostExecute afin que vous puissiez soyez sûr que cela n'arrivera pas simultanément. aussi le taskStatus est un ENUM. vous pouvez le vérifier en tant que telle non comme une chaîne comme:

task.getStatus()==Status.FINISHED 

dans votre cas si vous ne voulez pas faire la queue plusieurs tâches jusqu'à ce que la course est une complète alors faites actuellement quelque chose comme ceci:

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

L'annulation d'une tâche signifie que doInBackground s'exécutera mais que postExecute ne le sera pas. vous pouvez vérifier si la tâche estRunning afin de l'annuler pendant le traitement bg quelque part aussi.

+1

Ceci n'est pas documenté. Sur Android 1.5, toutes les tâches asynchrones étaient placées en file d'attente, sur Android 1.6+ plusieurs 'AsyncTask' pouvaient fonctionner en parallèle. Il est prévu de restaurer l'exécution "séquentielle" de "AsyncTask" dans les prochaines versions d'Android. Mais puisque cela n'est pas encore documenté, personne ne devrait se fier à ce comportement. (http://groups.google.com/group/android-developers/msg/3deeb36dccb4e9a5) – inazaruk

+0

Dois-je comprendre que la façon dont je le fais est erronée et cela va générer une erreur. J'ai compris ce que tu veux dire et tu l'as compris! Mais cela bloquera si je clique sur une nouvelle catégorie, je veux dire, je clique sur un lien différent (bouton) et rien ne se passe jusqu'à ce que l'instance actuelle de ** tâche ** soit terminée. Il est sécurisé, mais si la connexion au réseau de l'utilisateur est lente, il faudra quelques secondes pour la terminer. Existe-t-il un autre moyen d'interrompre la tâche en cours, sinon je vais mettre en œuvre de cette façon et considérer votre réponse comme correcte! – nenito

+0

Eh bien, la seule façon est de vérifier l'état pendant la tâche asynchrone. vous pouvez utiliser des threads. Ceux-ci sont exécutés en parallèle, ils sont un peu plus lourds, mais feront toujours le travail que vous voulez. Il y a aussi un projet de CommonsWare qui permet à deux tâches d'être exécutées en même temps. Recherchez AsyncTaskEx: http://code.google.com/p/alldroid/source/browse/trunk/AllDroid/src/com/commonsware/cwac/task/AsyncTaskEx.java?spec=svn24&r=24 – DArkO

2

Vous pouvez enregistrer la référence à AsyncTask dans la variable membre. Donc, votre code ressemblera à ceci:

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 
     } 
    } 
} 

Bien sûr, vous aurez besoin de mettre downloadTask à null dans onPostExecute() pour que cela fonctionne.


vous pouvez maintenant Comme un avantage supplémentaire annuler la tâche en cours si l'activité est détruite:

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

que vous devriez faire de toute façon.

+0

Il est stocké en tant que membre, Je n'ai juste pas partagé cette partie de la source. La vérification null est également effectuée. Merci pour '@Override onDestroy()' c'est vraiment utile. – nenito

Questions connexes