Au 15/2/2012, je n'ai pas encore trouvé une bonne explication ni une raison pour laquelle cela ne fonctionne pas. Le plus proche d'une solution est d'utiliser l' approche Thread traditionnelle , mais alors pourquoi inclure une classe qui ne fonctionne pas (semble) dans le SDK Android?
Evenin 'SO!
J'ai une sous-classe AsyncTask:
// ParseListener had a callback which was called when an item was parsed in a
// RSS-xml, but as stated further down it is not used at all right now.
private class xmlAsync extends AsyncTask<String, RSSItem, Void> implements ParseListener
Cela est exécuté comme ceci:
xmlAsync xmlThread = new xmlAsync();
xmlThread.execute("http://www.nothing.com");
Maintenant, cette sous-classe a rencontré une petite erreur. Auparavant, il effectuait une analyse XML, mais quand j'ai remarqué que doInBackground () n'était pas appelé, je l'ai dépouillé, ligne par ligne, pour finalement aboutir à ceci:
@Override
protected Void doInBackground(String... params)
{
Log.v(TAG, "doInBackground");
return null;
}
Qui, pour une raison quelconque, n'a rien enregistré. Cependant, j'ai ajouté ceci:
@Override
protected void onPreExecute()
{
Log.v(TAG, "onPreExecute");
super.onPreExecute();
}
Et cette ligne est en effet journalisée lors de l'exécution du thread. Donc en quelque sorte onPreExecute () est appelé mais pas doInBackground () . J'ai une autre AsyncTask en arrière-plan en même temps qui fonctionne très bien.
J'exécute actuellement l'application sur un émulateur, SDK version 15, Eclipse, Mac OS X 10.7.2, près du pôle Nord.
ÉDITER:
@Override
protected void onProgressUpdate(RSSItem... values) {
if(values[0] == null)
{
// activity function which merely creates a dialog
showInputError();
}
else
{
Log.v(TAG, "adding "+values[0].toString());
_tableManager.addRSSItem(values[0]);
}
super.onProgressUpdate(values);
}
_tableManager.addRSSItem () ajoute plus ou moins une ligne à une SQLiteDatabase, initialisée avec le contexte de l'activité. publishProgress () est appelé par le rappel de l'interface ParseListener. Cependant, comme je ne fais même rien d'autre que log.v dans doInBackground (), j'ai d'abord trouvé cela inutile même d'évoquer.
MODIFIER 2:
D'accord, juste pour être parfaitement clair, c'est l'autre AsyncTask, exécutée dans la même activité et fonctionnant parfaitement bien.
private class dbAsync extends AsyncTask<Void, RSSItem, Void>
{
Integer prevCount;
boolean run;
@Override
protected void onPreExecute() {
run = true;
super.onPreExecute();
}
@Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
run = true;
prevCount = 0;
while(run)
{
ArrayList<RSSItem> items = _tableManager.getAllItems();
if(items != null)
{
if(items.size() > prevCount)
{
Log.v("db Thread", "Found new item(s)!");
prevCount = items.size();
RSSItem[] itemsArray = new RSSItem[items.size()];
publishProgress(items.toArray(itemsArray));
}
}
SystemClock.sleep(5000);
}
return null;
}
@Override
protected void onProgressUpdate(RSSItem... values) {
ArrayList<RSSItem> list = new ArrayList<RSSItem>();
for(int i = 0; i < values.length; i++)
{
list.add(i, values[i]);
}
setItemsAndUpdateList(list);
super.onProgressUpdate(values);
}
@Override
protected void onCancelled() {
run = false;
super.onCancelled();
}
}
MODIFIER 3:
Soupir, désolé, je suis mauvais pour poser des questions. Mais voici l'initialisation des tâches.
xmlAsync _xmlParseThread;
dbAsync _dbLookup;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
_dbLookup = new dbAsync();
_dbLookup.execute();
_xmlParseThread = new xmlAsync();
_xmlParseThread.execute("http://www.nothing.com", null);
}
Réponses:
La solution de Matthieu fonctionnera bien pour la plupart, mais certains peuvent rencontrer des problèmes; à moins de creuser dans de nombreux liens fournis ici ou sur le Web, comme l' explication d' Anders Göransson . J'essaie de résumer quelques autres lectures ici et d'expliquer rapidement la solution si executeOnExecutor fonctionne toujours en un seul thread ...
Le comportement de
AsyncTask().execute();
a changé avec les versions d'Android. Avant Donut (Android: 1.6 API: 4), les tâches étaient exécutées en série, de Donut à Gingerbread (Android: 2.3 API: 9), les tâches exécutées en parallèle; depuis l' exécution de Honeycomb (Android: 3.0 API: 11) est revenue au séquentiel; une nouvelle méthode aAsyncTask().executeOnExecutor(Executor)
cependant été ajoutée pour l'exécution parallèle.Dans le traitement séquentiel, toutes les tâches Async s'exécutent dans un seul thread et doivent donc attendre la fin de la tâche précédente. Si vous devez exécuter du code immédiatement, vous avez besoin que les tâches soient traitées en parallèle dans des threads séparés.
Avec AsyncTask, l'exécution en série n'est pas disponible entre les versions Donut et Honeycomb, tandis que l'exécution parallèle n'est pas disponible avant Donut.
Pour le traitement parallèle après Donut: vérifiez la version de Build et en fonction de celle-ci, utilisez la méthode .execute () ou .executeOnExecutor (). Le code suivant peut vous aider ...
NOTE:
La fonction.executeOnExecutor()
vérifie si letargetSdkVersion
projet est inférieur ou égal àHONEYCOMB_MR1
(Android: 2.1 API: 7) puis force l'exécuteur à êtreTHREAD_POOL_EXECUTOR
(qui exécute les tâches séquentiellement dans post Honeycomb).Si vous n'avez pas défini de,
targetSdkVersion
alorsminSdkVersion
est automatiquement considéré comme letargetSdkVersion
.Par conséquent, pour exécuter votre AsyncTask en parallèle sur post Honeycomb, vous ne pouvez pas laisser
targetSdkVersion
vide.la source
Vous devriez vérifier cette réponse: https://stackoverflow.com/a/10406894/347565 et le lien vers les groupes Google qu'il comprend.
J'ai eu un problème similaire à vous, je ne sais toujours pas pourquoi cela ne fonctionne pas, mais j'ai changé mon code comme ceci et le problème a disparu:
la source
Vous pouvez le faire de deux manières:
Voie 1 :
En cas de façon 1 fonctionne pas pour vous essayer ainsi 2 .
Voie 2 :
J'espère que ceci vous aidera.
la source
J'ai eu le même problème: impossible d'exécuter une deuxième AsyncTask après avoir appelé "exécuter" sur une première: doInBackground n'est appelé que pour le premier.
Pour savoir pourquoi cela se produit, vérifiez cette réponse (comportement différent selon le SDK)
Cependant, pour votre cas, cet obstacle peut être évité en utilisant executeOnExecutor (disponible à partir de 3.0 a fonctionné pour moi en utilisant 4.0.3) mais méfiez-vous des limitations de la taille du pool de threads et de la file d'attente.
Pouvez-vous essayer quelque chose comme ça:
Pour votre question de mise à jour: elle est expliquée dans la documentation En gros, juste pour éviter tous les problèmes qui peuvent provenir du multithreading comme l'interférence ....
la source
Une chose que j'aimerais savoir, et qui pourrait en fait résoudre votre problème, est où instanciez-vous l'instance de votre classe et appelez-vous la méthode execute ()? Si vous lisez la documentation d'AsyncTask, ces deux opérations doivent avoir lieu sur le thread d'interface utilisateur principal. Si vous créez votre objet et appelez execute à partir d'un autre thread, alors onPreExecute peut se déclencher, je ne suis pas sûr à 100% ici, mais le thread d'arrière-plan ne sera pas créé et exécuté.
Si vous créez l'instance de votre AsyncTask à partir d'un thread d'arrière-plan ou d'une autre opération qui n'a pas lieu sur le thread d'interface utilisateur principal, vous pouvez envisager d'utiliser la méthode: Activity.runOnUiThread (Runnable)
Vous auriez besoin d'accéder à une instance de votre activité en cours d'exécution pour appeler cette méthode, mais cela vous permettra d'exécuter du code sur le thread d'interface utilisateur à partir d'un autre code qui ne s'exécute pas sur le thread d'interface utilisateur.
J'espère que cela a du sens. Faites-moi savoir si je peux vous aider davantage.
David
la source
Android est Brutal! Je ne peux pas croire cela, quelle implémentation floconneuse qui change de jour en jour. Un jour, c'est un seul fil, le suivant, c'est 5, l'autre est 128.
Quoi qu'il en soit, voici une quasi-baisse de remplacement pour le stock AsyncTask. Vous pouvez même l'appeler AsyncTask si vous le souhaitez, mais pour éviter toute confusion, il s'appelle ThreadedAsyncTask. Vous devez appeler executeStart () au lieu de execute car execute () est final.
la source
Je sais que cela peut être très tard pour le fil, mais il y a une raison pour laquelle cela ne fonctionnera pas sur les émulateurs Android ultérieurs. Quand asynctask a été introduit, Android ne vous a laissé en exécuter qu'une à la fois, puis un peu plus tard, je ne sais pas quelle version, ils vous ont permis d'exécuter plusieurs asynctasks à la fois, cela a causé des problèmes dans beaucoup d'applications, et donc dans Honeycomb +, ils sont revenus à seulement permettant à une asynctask de s'exécuter à la fois. Sauf si vous modifiez manuellement le pool de threads. J'espère que cela clarifie une ou deux choses pour les gens.
la source
je pense que c'est le sdk. J'ai eu le même problème, et après avoir changé le SDK cible de 15 à 11, tout fonctionne parfaitement.
avec sdk15, même si le AsyncTask.Status est en cours d'exécution, le doInBackground n'est jamais appelé. Je pense que cela a quelque chose à voir avec le thread de l'interface utilisateur.
la source
Sur la base de la réponse de Matthieu, ci-dessous une classe d' aide pour exécuter votre
AsyncTask
correctement en fonction de la version du SDK afin d'éviter de dupliquer du code dans votre application:Exemple d'utilisation:
...
la source