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.

Était-ce utile?

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

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

scroll top