34 votes

AsyncTask doInBackground ne s'exécute pas

Je vais avoir un problème avec la classe AsyncTask. Il semble que ma tâche s'arrête de fonctionner après la création de 4 ou 5 tâches.

Je vais avoir 2 activités. MainActivity qui ne détient qu'un bouton qui lance une deuxième activité est appelée ImageActivity.

ImageActivity est très simple. il a obtenu un onCreate qui définit la mise en page, et puis il commence une nouvelle AsyncTask qui charge une image à partir d'internet. Cela fonctionne bien pour les premières fois. Mais qu'il s'arrête soudainement de fonctionner. Le onPreExecute méthode est exécutée à chaque fois, mais pas la méthode doInBackground. J'ai essayé de simplifier le doInBackground avec un couchage de boucle, et la même chose arrive. Je ne peux pas comprendre ce comportements depuis l'asynctask est à la fois annulée et la valeur null dans la méthode onDestroy. Donc, à chaque fois que je commence un nouveau ImageActivity, j'ai aussi créer une nouvelle AsyncTask.

Je recrée le ImageActivity et les tâches en appuyant sur le bouton de retour, et qu'en cliquant sur le bouton sur le MainActivity.

Toutes les idées de quelqu'un? J'ai vraiment du mal avec celui-ci.

Mise à JOUR: le Code qui commence le ImageActivity (à l'intérieur d'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 court à 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:

J'ai testé à l'aide d'une combinaison de traditionnelle Fils et runOnUiThread méthode, et il semble fonctionner mieux. Maintenant le thread s'exécute à chaque fois.

24voto

Vidar Vestnes Points 14317

Supprimer la tâche asynchrone et utiliser un thread traditionnel à la place, associé à runOnUiThread, semble être un travail. Mais je n'ai toujours pas trouvé la raison pour laquelle 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();
    }
}
 

7voto

ericwjr Points 106

J'ai rencontré un problème similaire. Vous ne pouvez pas avoir plusieurs Asynchrones fonctionnant en parallèle jusqu'au SDK 11. Vérifiez ici pour plus d'informations.

6voto

Heath Borders Points 8067

Je viens de tomber sur ce problème. Si vous utilisez AsyncTask.execute, votre tâche est exécutée sur une série de file d'attente (à partir de l'Android 4.3 source):

Lors de sa première apparition, AsyncTasks ont été exécutés en série sur un seul thread d'arrière-plan. En commençant par DONUT, cela a été changé pour une piscine de les threads qui permet de réaliser plusieurs tâches en parallèle. En commençant par NID d'abeille, les tâches sont exécutées sur un seul thread pour éviter les demande d'erreurs causées par l'exécution en parallèle.

Ceci est cohérent avec le comportement que j'ai vu. J'ai eu un AsyncTask surgi d'un dialogue en doInBackground et bloqué jusqu'à ce que la boîte de dialogue est fermée. La boîte de dialogue de sa propre AsyncTask pour terminer. La boîte de dialogue de l' AsyncTask.doInBackground méthode jamais exécuté parce que l'original AsyncTask était toujours bloqué.

La solution consiste à exécuter la deuxième AsyncTask dans un autre Executor.

1voto

Dustin Points 4694

Utilisez traceview pour enquêter - ou obtenez un vidage de thread. À mon avis, l’un de vos threads AsyncTask est en attente de téléchargement.

AsyncTask a un petit pool de threads; ainsi, si l'une de vos tâches est suspendue, elle risque de bloquer votre pool de threads.

Voici un test rapide que vous pouvez exécuter - sur la version 4.3, je constate que je ne peux exécuter que 5 threads simultanés. Lorsqu'un thread se ferme, d'autres threads démarrent.

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

        }
  }
 

0voto

Octavian Damiean Points 20620

Vous ne devriez pas avoir à vous soucier du fil de maintenance dans Android, car il est géré par le système.

S'il vous plaît également poster 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 retournez-vous l'image dans votre thread d'interface utilisateur?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X