web-dev-qa-db-fra.com

Android: RunOnUiThread vs AsyncTask

Je crois que Google suggère aux développeurs d'utiliser AsyncTask. Cependant, j'aimerais savoir en quoi est-ce différent d'utiliser "nouveau thread" et d'appeler ensuite "RunOnUiThread" en termes de performances et d'efficacité de la mémoire.

Exemple d'utilisation de RunOnUithread:

    // some code #1
    Thread t = new Thread("Thread1") {
        @Override
        public void run() {
            // some code #2
            runOnUiThread(new Runnable() {
                public void run() {
                    // some code #3 (that needs to be ran in UI thread)

                }
            });

        }
    };
    t.start();

vs.

AsyncTask:

onPreExecute() {
   // some code #1
}

doInBackground() {
   // some code #2
}

onPostExecute() {
   // some code #3
}

Quels sont les avantages/inconvénients?

Éditer:

Je ne cherche pas de réponses comme "plus facile à voir le code", "pratique pour les développeurs", etc. Je recherche en fait des différences techniques derrière la scène.

Par exemple, la réponse de Paul Nikonowicz ci-dessous aurait été la réponse que je voulais voir. (Mais AsyncTask se comporte de la même manière)

36
jclova

Lorsque vous utilisez new Thread vous créez vraiment un nouveau thread à chaque fois que vous l'exécutez. AsyncTask utilise cependant un pool statique de 128 threads maximum et réutilisera un ancien thread chaque fois qu'il existera. Ainsi, exécuter AsyncTask 10 fois en série ne créera qu'un seul thread qui exécutera la tâche 10 fois au lieu de 10 threads.

C'est l'une des différences parmi tant d'autres.

51
Randy Sugianto 'Yuku'

C'est une commodité, essentiellement. Le framework AsyncTask traite de la gestion du pool Thread et fournit une interface simple et compréhensible. Il est bien connu - par ceux qui savent utiliser AsyncTask - que l'activité de l'interface utilisateur peut se poursuivre dans onPreExecute(), onPostExecute() et onProgressUpdate(), et que tout le "levage de charges lourdes" se fait dans doInBackground() où vous ne pouvez pas toucher l'interface utilisateur.

Cela permet au développeur d'avoir facilement une tâche d'arrière-plan simple qui peut facilement publier des mises à jour du thread d'interface utilisateur et retourner des résultats une fois terminé. Ce n'est pas magique, c'est juste une commodité.

12
Brian Dupuis

Le principal inconvénient est que l'utilisation de votre propre fil gardera votre activité en vie lorsque la fin sera appelée. Android donnera à votre activité le temps de terminer tous vos threads. Cela a pour effet de créer une fuite d'activité qui entraînera éventuellement le ralentissement de votre application jusqu'à ce que votre application soit forcée de quitter soit l'utilisateur ou le système d'exploitation.

Vous pouvez le vérifier en consultant votre processus dans ADB. Même lorsque l'activité est terminée, vous la verrez toujours accrochée là, occupant des ressources.

Donc, si vous utilisez votre propre fil, assurez-vous de le gérer. Ou, utilisez simplement les API Android. Le choix vous appartient.

4
Paul Nikonowicz

Selon this , AsyncTask est plus facile à utiliser, mais présente certaines limitations comme les suivantes:

  • La taille du pool principal et la file d'attente de travail sont fixes: 5 pools/10 éléments
    • il est codé en dur et ne peut pas être changé
  • La priorité des threads est fixée à faible
  • La gestion des exceptions n'est pas aussi bien prise en charge qu'avec Thread

Il y aura également une autre différence que je n'ai pas comprise. Vous pouvez trouver et inspecter code source complet d'AsyncTask puisque Android est opensource :-)

Passez un bon moment avec le codage dans Android!

4
Joon Hong

Ce sont énormément différents.

  • D'abord, TOUTES les interactions utilisateur se font sur le thread principal ainsi que sur tous les travaux graphiques.
  • Le deuxième AsyncTask est conçu pour de courtes périodes d'activité dédiée, comme le téléchargement d'un fichier ou le téléchargement de certaines données.
  • Troisièmement, car toutes les interactions avec l'interface utilisateur et l'utilisateur se font dans le thread principal, si vous commencez à pousser des éléments vers ce thread, l'appareil semblera être en retard et moins réactif aux commandes de l'utilisateur.

La seule raison pour laquelle vous souhaitez exécuter quelque chose dans le thread d'interface utilisateur est d'interagir avec des widgets. Sinon, si vous souhaitez effectuer un traitement long, utilisez un AsyncTask.

Éditer:

Vous pouvez télécharger vos données dans un fil séparé, et je n'ai aucun problème avec cela. Le problème survient lorsque vous souhaitez mettre à jour l'interface utilisateur. Seul, il est impossible de modifier l'interface utilisateur à partir d'un thread enfant. Au lieu de cela, vous devrez créer un gestionnaire lié au thread d'interface utilisateur ou créer un nouveau thread destiné à s'exécuter dans le thread d'interface utilisateur (comme dans votre exemple). C'est non seulement fastidieux, mais un tragique gaspillage de ressources. AsyncTask s'occupe de cela simplement et efficacement.

Pour répondre à votre dernier point, vous avez raison. AsyncTask a accès au thread principal dans pre/postExecute. Cependant, le traitement (la principale source du décalage de l'interface utilisateur) que la tâche effectue n'est pas. Avec la tâche, l'interface utilisateur ne sera affectée qu'en fonction de ce que vous dessinez, par opposition à devoir attendre que la tâche termine son travail et quel que soit le dessin qu'elle souhaite faire.

1
ahodder