AsyncTask doInBackground ne fonctionne pas [double]
-
28-09-2019 - |
Question
Cette question a déjà une réponse ici:
Je suis un problème avec la classe AsyncTask. Il semble que mes arrêts de travail de travail après avoir créé 4 ou 5 tâches.
Im ayant 2 activités. MainActivity qui ne détient qu'un bouton qui lance une seconde activité appelée ImageActivity.
ImageActivity est très simple. il a obtenu un onCreate qui définit la mise en page, puis il commence une nouvelle AsyncTask qui charge une image de l'Internet. Cela fonctionne très bien les premières fois. Mais qu'il cesse brusquement de fonctionner. La méthode OnPreExecute est exécuté à chaque fois, mais pas la méthode doInBackground. J'ai essayé de simplifier la doInBackground avec une boucle de couchage, et la même chose se passe. Je ne comprends pas ce behavour depuis le AsyncTask est à la fois annulé et mis à zéro dans la méthode OnDestroy. Ainsi, chaque fois que je commence une nouvelle ImageActivity, je crée aussi un AsyncTask frais.
Je Recréez le ImageActivity et la tâche en appuyant sur le bouton de retour, et que de cliquer sur le bouton du MainActivity.
Toute personne idées? Je suis vraiment aux prises avec celui-ci.
MISE À JOUR: Le code qui commence le ImageActivity (dans un bouton onClickListener)
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
intent.setClassName(this, ImageActivity.class.getName());
startActivity(intent);
Le code ci-dessus commence cette activité
public class ImageActivity extends Activity {
private AsyncTask<Void, Void, Void> task;
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.main);
task = new AsyncTask<Void, Void, Void>() {
@Override
protected void onPreExecute()
{
Log.d(TAG, "onPreExecute()");
}
@Override
protected Void doInBackground(Void... params)
{
Log.d(TAG, "doInBackground() -- Here is the download");
// downloadBitmap("http://mydomain.com/image.jpg")
return null;
}
@Override
protected void onPostExecute(Void res)
{
Log.d(TAG, "onPostExecute()");
if(isCancelled()){
return;
}
}
}.execute();
}
@Override
protected void onDestroy()
{
super.onDestroy();
task.cancel(true);
}
}
MISE À JOUR:
Je l'ai testé en utilisant une combinaison de threads traditionnels et méthode runOnUiThread, et il semble fonctionner mieux. Maintenant, le fil passe à chaque fois.
La solution
Retrait de la AsyncTask et en utilisant un Discussion traditionnelle au lieu de le combiner avec runOnUiThread semble fonctionner. Mais je l'ai toujours pas trouvé la raison pour laquelle la AsyncTask est si « instable ».
Voici le code qui fonctionne pour moi:
public class ImageActivity extends Activity {
private Thread worker;
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.main);
worker = new Thread(new Runnable(){
private void updateUI(final List<Object> list)
{
if(worker.isInterrupted()){
return;
}
runOnUiThread(new Runnable(){
@Override
public void run()
{
// Update view and remove loading spinner etc...
}
});
}
private List<Object> download()
{
// Simulate download
SystemClock.sleep(1000);
return new ArrayList<Object>();
}
@Override
public void run()
{
Log.d(TAG, "Thread run()");
updateUI(download());
}
});
worker.start(); }
@Override
protected void onDestroy()
{
super.onDestroy();
worker.interrupt();
}
}
Autres conseils
Je suis tombé sur le même problème. Vous ne pouvez pas avoir plusieurs Asynctasks fonctionnant en parallèle jusqu'à SDK 11. Vérifiez
Je viens de croiser ce problème aussi bien. Si vous utilisez Lorsque la première, AsyncTasks ont été exécutés en série sur un seul
fil de fond. A partir de beignet, cela a été changé à un bassin de
fils permettant de multiples tâches de fonctionner en parallèle. Commençant par
HONEYCOMB, les tâches sont exécutées sur un seul thread pour éviter commun
erreurs d'application causées par l'exécution en parallèle. Ceci est cohérent avec le comportement que j'ai vu. J'ai eu un La solution consiste à exécuter la deuxième AsyncTask.execute
, votre tâche est exécutée sur une file d'attente de série (à partir de la source Android 4.3):
AsyncTask
sauté une boîte de dialogue dans doInBackground
et bloqué jusqu'à ce que la boîte de dialogue a été fermé. La boîte de dialogue avait besoin de son propre AsyncTask
à remplir. La méthode de AsyncTask.doInBackground
de dialogue n'a jamais été exécuté parce que le AsyncTask
d'origine était toujours bloquée. AsyncTask
dans un Executor
séparé.
Utilisez TraceView pour enquêter sur - ou obtenir une décharge de fil. Je pense que l'un de vos fils AsyncTask sont suspendus sur le téléchargement.
AsyncTask a une petite piscine de fil, donc si l'un de vos tâches se bloque, il pourrait finir par bloquer votre pool de threads.
Voici un test rapide, vous pouvez exécuter - sur 4.3, je vois que j'ai seulement 5 threads simultanés que je peux courir. Quand on sort de fil, d'autres threads démarrage.
private void testAsyncTasks() {
for (int i = 1; i <= 10; i++) {
final int tid = i;
new AsyncTask<Integer, Void, Void>() {
protected void onPreExecute() {
Log.d("ASYNCTASK", "Pre execute for task : " + tid);
};
@Override
protected Void doInBackground(Integer... args) {
int taskid = args[0];
long started = SystemClock.elapsedRealtime();
Log.d("ASYNCTASK", "Executing task: " + taskid + " at " + started);
for (int j = 1; j <= 20; j++) {
Log.d("ASYNCTASK", " task " + taskid + ", time=" + (SystemClock.elapsedRealtime() - started));
SystemClock.sleep(1000);
}
return null;
}
protected void onPostExecute(Void result) {
Log.d("ASYNCTASK", "Post execute for task : " + tid);
};
}.execute(i);
}
}
Vous ne devriez pas avoir à vous soucier de fil de ménage dans Android comme il est géré par le système.
S'il vous plaît poster aussi la méthode de téléchargement d'image. Avez-vous également essayé de ne pas annuler le fil dans la méthode OnDestroy ()? Comment allez-vous restituez le l'image à votre thread d'interface utilisateur?
Le problème que je crois est la tâche de téléchargement d'image lourde. Même si vous annulez la tâche async le téléchargement de l'image continuera à exécuter et la tâche async ne se termine pas jusqu'à ce que le téléchargement est terminé. Vous pouvez vérifier la méthode isCancelled () sur AyncTask alors que le téléchargement est en cours et tuer le téléchargement si la tâche est annulée.
Pour référence, Heres la documentation sur la méthode cancel (): Les tentatives visant à annuler l'exécution de cette tâche. Cette tentative échouera si la tâche a déjà terminé, déjà été annulée, ou ne peut pas être annulée pour une autre raison. En cas de succès, et cette tâche n'a pas commencé quand d'annulation est appelée, cette tâche ne doit jamais courir. Si la tâche a déjà commencé, le paramètre de mayInterruptIfRunning détermine si le thread d'exécuter cette tâche doit être interrompue pour tenter d'arrêter la tâche. L'appel de cette méthode se traduira par onCancelled (Object) invoquée sur le thread d'interface utilisateur après doInBackground (Object []) les retours. L'appel de cette méthode garantit que onPostExecute (Object) est jamais invoqué. Après avoir invoqué cette méthode, vous devriez vérifier la valeur retournée par isCancelled () périodiquement doInBackground (Object []) pour terminer la tâche le plus tôt possible.
J'ai eu cela aussi, aucune raison pour ne pas commencer. Je l'ai remarqué qu'après le redémarrage adb, il a travaillé à nouveau. Je ne sais pas pourquoi il en est, mais il a travaillé pour moi