Handler vs AsyncTask vs Thread [fermé]


382

Je me suis un peu confus au sujet des différences entre Handlers, AsyncTasket Threadsdans Android. J'ai lu pas mal de blogs et de questions ici dans StackOverflow.

Handlersont des fils d'arrière-plan qui vous permettent de communiquer avec l'interface utilisateur. La mise à jour d'une barre de progression, par exemple, doit être effectuée via Handler. L'utilisation des gestionnaires vous offre l'avantage MessagingQueues, donc si vous souhaitez planifier des messages ou mettre à jour plusieurs éléments d'interface utilisateur ou effectuer des tâches répétitives.

AsyncTasksont similaires, en fait, ils utilisent Handler, mais ne s'exécutent pas dans le thread d'interface utilisateur, c'est donc bon pour récupérer des données, par exemple pour récupérer des services Web. Plus tard, vous pourrez interagir avec l'interface utilisateur.

Threadcependant ne peut pas interagir avec l'interface utilisateur, fournir un filetage plus "basique" et vous manquez toutes les abstractions de AsyncTask.

Cependant, je voudrais avoir une connexion socket exécutée en service. Si cela doit être exécuté dans un gestionnaire ou un thread, ou même unAsyncTask ? L'interaction avec l'interface utilisateur n'est pas du tout nécessaire. Cela fait-il une différence en termes de performances que j'utilise?

Pendant ce temps, la documentation a été considérablement améliorée.



9
"Les gestionnaires sont des fils d'arrière-plan" - Certaines des réponses les plus votées semblent aller dans ce sens également. Mais c'est une idée fausse. A Handlern'est pas un thread et n'exécute rien. Ce n'est qu'un moyen de transmettre en toute sécurité des messages d'un thread à la file d'attente de messages d'un autre thread . Donc, normalement, (au moins) deux threads doivent toujours être créés qui peuvent ensuite utiliser un gestionnaire, mais le gestionnaire ne peut rien exécuter lui-même.
JimmyB

Réponses:


57

En tant que tutoriel sur le traitement d'arrière-plan Android avec les gestionnaires, AsyncTask et les chargeurs sur le site Vogella:

le Handler classe peut être utilisée pour s'inscrire à un thread et fournit un canal simple pour envoyer des données à ce thread.

le AsyncTask classe encapsule la création d'un processus d'arrière-plan et la synchronisation avec le thread principal. Il prend également en charge la génération de rapports sur la progression des tâches en cours d'exécution.

Et a Threadest fondamentalement l'élément central du multithreading qu'un développeur peut utiliser avec l'inconvénient suivant:

Si vous utilisez des threads Java, vous devez gérer les exigences suivantes dans votre propre code:

  • Synchronisation avec le thread principal si vous publiez des résultats sur l'interface utilisateur
  • Aucun défaut pour annuler le fil
  • Aucun regroupement de threads par défaut
  • Aucune valeur par défaut pour gérer les modifications de configuration dans Android

Et en ce qui concerne le AsyncTask, comme le dit la référence du développeur Android :

AsyncTaskpermet une utilisation correcte et facile du thread d'interface utilisateur. Cette classe permet d'effectuer des opérations en arrière-plan et de publier les résultats sur le thread d'interface utilisateur sans avoir à manipuler les threads et / ou les gestionnaires.

AsyncTaskest conçu pour être une classe d'aide autour Threadet Handler et ne constitue pas un cadre de filetage générique. AsyncTasks devrait idéalement être utilisé pour des opérations courtes (quelques secondes tout au plus.) Si vous devez garder les threads en cours d'exécution pendant de longues périodes, il est fortement recommandé d'utiliser les différentes API fournies par le package java.util.concurrent tel que Executor, ThreadPoolExecutor et FutureTask.

Mise à jour de mai 2015: j'ai trouvé une excellente série de conférences couvrant ce sujet.

Ceci est la recherche Google: conférence Douglas Douglas et synchronisation Android

Ceci est la vidéo de la première conférence sur YouTube

Tout cela fait partie du CS 282 (2013): Programmation de systèmes pour Android de l' Université Vanderbilt . Voici la liste de lecture YouTube

Douglas Schmidt semble être un excellent conférencier

Important: Si vous êtes à un point où vous envisagez d'utiliser AsyncTaskpour résoudre vos problèmes de filetage, vous devez d' abord vérifierReactiveX/RxAndroid pour un modèle de programmation peut - être plus approprié. Une très bonne ressource pour obtenir un aperçu est l' apprentissage de RxJava 2 pour Android par exemple .


4
Dans cette série de conférences, ce lien vous emmènera directement dans quelques exemples de fils: youtu.be/4Vue_KuXfCk?t=19m24s
Aggressor

353

Si nous regardons le code source, nous verrons AsyncTasketHandler est purement écrit en Java. (Il y a cependant quelques exceptions. Mais ce n'est pas un point important)

Il n'y a donc pas de magie dans AsyncTaskou Handler. Ces cours nous facilitent la vie en tant que développeur.

Par exemple: si le programme A appelle la méthode A (), la méthode A () peut s'exécuter dans un thread différent avec le programme A. Nous pouvons facilement vérifier en utilisant le code suivant:

Thread t = Thread.currentThread();    
int id = t.getId();

Pourquoi devrions-nous utiliser un nouveau thread pour certaines tâches? Vous pouvez google pour cela. De nombreuses raisons, par exemple: levage lourd, travaux de longue durée.

Alors, quelles sont les différences entre Thread, AsyncTasket Handler?

AsyncTasket Handlersont écrits en Java (en interne, ils utilisent un Thread), donc tout ce que nous pouvons faire avec Handlerou AsyncTask, nous pouvons réaliser en utilisant unThread aussi.

Qu'est-ce qui peut Handleret peut AsyncTaskvraiment aider?

La raison la plus évidente est la communication entre le thread appelant et le thread travailleur. ( Fil de l'appelant : Un fil qui appelle le fil de travail pour effectuer certaines tâches. Un fil de l'appelant ne doit pas nécessairement être le fil de l'interface utilisateur). Bien sûr, nous pouvons communiquer entre deux threads de différentes manières, mais il existe de nombreux inconvénients (et dangers) en raison de la sécurité des threads.

C'est pourquoi nous devrions utiliser Handleret AsyncTask. Ces classes font la plupart du travail pour nous, nous avons seulement besoin de savoir quelles méthodes remplacer.

La différence entre Handleret AsyncTaskest: à utiliser AsyncTasklorsque le thread de l'appelant est un thread d'interface utilisateur . Voici ce que dit le document Android:

AsyncTask permet une utilisation correcte et facile du thread d'interface utilisateur. Cette classe permet d'effectuer des opérations en arrière-plan et de publier les résultats sur le thread d'interface utilisateur sans avoir à manipuler les threads et / ou les gestionnaires

Je veux souligner deux points:

1) Utilisation facile du thread d'interface utilisateur (donc, utilisez lorsque le thread d'appelant est le thread d'interface utilisateur).

2) Pas besoin de manipuler les gestionnaires. (signifie: vous pouvez utiliser Handler au lieu d'AsyncTask, mais AsyncTask est une option plus simple).

Il y a beaucoup de choses dans ce post que je n'ai pas encore dites, par exemple: qu'est-ce que le thread d'interface utilisateur, ou pourquoi c'est plus facile. Vous devez connaître certaines méthodes derrière chaque classe et les utiliser, vous en comprendrez parfaitement la raison.

@: lorsque vous lirez le document Android, vous verrez:

Le gestionnaire vous permet d'envoyer et de traiter des objets Message et Runnable associés à MessageQueue d'un thread

Cette description peut sembler étrange au premier abord. Nous devons seulement comprendre que chaque thread a chaque file d'attente de messages (comme une liste de tâches), et le thread prendra chaque message et le fera jusqu'à ce que la file d'attente de messages soit vide (tout comme nous terminons notre travail et nous couchons). Donc quandHandler communique, il donne simplement un message au thread appelant et attendra d'être traité.

Compliqué? N'oubliez pas que cela Handlerpeut communiquer avec le fil de l'appelant en toute sécurité.


4
en fait, asynctask est également basé sur handler et futuretask, voir
Sumit

AsyncTask est essentiellement une classe d'assistance construite au-dessus de Handler et Thread. developer.android.com/reference/android/os/AsyncTask.html . Regardez le document "AsyncTask est conçu pour être une classe d'assistance autour de Thread and Handler". AsyncTask est publié dans API3 tandis que le gestionnaire existe depuis API1.
hjchin

52

Après avoir regardé en profondeur, c'est simple.

AsyncTask:

C'est un moyen simple d'utiliser un thread sans rien savoir du modèle de thread java . AsyncTaskdonne divers rappels respectifs au thread de travail et au thread principal.

À utiliser pour les petites opérations en attente comme les suivantes:

  1. Récupération de certaines données des services Web et affichage sur la mise en page.
  2. Requête de base de données.
  3. Lorsque vous réalisez que l'opération en cours ne sera jamais, jamais imbriquée.

Handler:

Lorsque nous installons une application dans Android, il crée un thread pour cette application appelé MAIN UI Thread. Toutes les activités s'exécutent à l'intérieur de ce fil. Selon la règle du modèle de thread unique Android, nous ne pouvons pas accéder directement aux éléments d'interface utilisateur (bitmap, textview, etc.) pour un autre thread défini à l'intérieur de cette activité.

Un gestionnaire vous permet de communiquer avec le thread d'interface utilisateur à partir d'autres threads d'arrière-plan. Ceci est utile dans Android car Android ne permet pas aux autres threads de communiquer directement avec le thread d'interface utilisateur. Un gestionnaire peut envoyer et traiter des objets Message et Runnable associés à MessageQueue d'un thread. Chaque instance de gestionnaire est associée à un seul thread et à la file d'attente de messages de ce thread. Lorsqu'un nouveau gestionnaire est créé, il est lié à la file d'attente des threads / messages du thread qui le crée.

C'est le meilleur choix pour:

  1. Il vous permet de faire la file d'attente de messages.
  2. Planification des messages.

Thread:

Il est maintenant temps de parler du fil.

Le thread est le parent des deux AsyncTasket Handler. Ils utilisent tous deux en interne un thread, ce qui signifie que vous pouvez également créer votre propre modèle de thread comme AsyncTasket Handler, mais cela nécessite une bonne connaissance de l' implémentation multi-threading de Java .


1
L'API AsyncTask est en fait écrite avec Futures, Handlers et Executors. Voir le code source: grepcode.com/file_/repository.grepcode.com/java/ext/…
IgorGanapolsky

22

Un AsyncTaskest utilisé pour effectuer des calculs d'arrière-plan et publier le résultat sur le thread d'interface utilisateur (avec des mises à jour de progression facultatives). Puisque vous n'êtes pas concerné par l'interface utilisateur, un Handlerou Threadsemble plus approprié.

Vous pouvez frayer un arrière - plan Threadet transmettre des messages de retour à votre thread principal en utilisant le Handlerde postméthode.


9

Fil

Android prend en charge les threads Java standard . Vous pouvez utiliser les threads standard et les outils du package « java.util.concurrent» pour mettre les actions en arrière-plan. La seule limitation est que vous ne pouvez pas mettre à jour directement l'interface utilisateur à partir d'un processus d'arrière-plan.

Si vous devez mettre à jour l'interface utilisateur à partir d'une tâche d'arrière-plan, vous devez utiliser certaines classes spécifiques à Android. Vous pouvez utiliser la classe "android.os.Handler » pour cela ou la classe « AsyncTask»

Gestionnaire

La classe « Handler» peut mettre à jour l'interface utilisateur. Un handle fournit des méthodes pour recevoir des messages et pour les runnables. Pour utiliser un gestionnaire, vous devez le sous-classer et le remplacer handleMessage()pour traiter les messages. Pour traiter Runable, vous pouvez utiliser la méthodepost(); Vous n'avez besoin que d'une seule instance d'un gestionnaire dans votre activité.

Votre thread peut publier des messages via la méthode sendMessage(Message msg)ousendEmptyMessage .

AsyncTask

Si vous en avez un Activityqui doit télécharger du contenu ou effectuer des opérations qui peuvent être effectuées en arrière-planAsyncTask vous permet de maintenir une interface utilisateur réactive et de publier la progression de ces opérations à l'utilisateur.

Pour plus d'informations, vous pouvez consulter ces liens.

http://mobisys.in/blog/2012/01/android-threads-handlers-and-asynctask-tutorial/

http://www.slideshare.net/HoangNgoBuu/android-thread-handler-and-asynctask


6

Thread:

Vous pouvez utiliser le nouveau Threadpour les tâches d'arrière-plan de longue durée sans impact sur le thread d'interface utilisateur. À partir de Java Thread, vous ne pouvez pas mettre à jour le thread d'interface utilisateur.

Étant donné que le thread normal n'est pas très utile pour l'architecture Android, des classes d'assistance pour le thread ont été introduites.

Vous pouvez trouver des réponses à vos questions dans Threading performance page de documentation des .

Gestionnaire :

A Handlervous permet d'envoyer et de traiter des messages et des Runnableobjets associés à un thread MessageQueue. Chaque Handlerinstance est associée à un seul thread et à la file d'attente de messages de ce thread.

Il y a deux utilisations principales pour un Handler:

  1. Pour planifier des messages et des runnables à exécuter à un moment donné dans le futur;

  2. Pour mettre en file d'attente une action à exécuter sur un thread différent du vôtre.

AsyncTask :

AsyncTaskpermet une utilisation correcte et facile du thread d'interface utilisateur. Cette classe vous permet d'effectuer des opérations d'arrière-plan et de publier des résultats sur le thread d'interface utilisateur sans avoir à manipuler des threads et / ou des gestionnaires.

Désavantages:

  1. Par défaut, une application pousse tous les AsyncTaskobjets qu'elle crée dans un seul thread. Par conséquent, ils s'exécutent en mode série et, comme avec le thread principal, un paquet de travail particulièrement long peut bloquer la file d'attente. Pour cette raison, utilisez AsyncTask pour gérer les éléments de travail d'une durée inférieure à 5 ms .

  2. AsyncTaskles objets sont également les contrevenants les plus courants pour les problèmes de référence implicite. AsyncTaskles objets présentent également des risques liés aux références explicites.

HandlerThread :

Vous devrez peut-être une approche plus traditionnelle pour exécuter un bloc de travail sur un thread de longue durée ( contrairement à AsyncTask, qui devrait être utilisé pour une charge de travail de 5 ms ), et une certaine capacité à gérer ce flux de travail manuellement. Un thread de gestionnaire est effectivement un thread de longue durée qui récupère le travail d'une file d'attente et opère dessus.

ThreadPoolExecutor :

Cette classe gère la création d'un groupe de threads, définit leurs priorités et gère la répartition du travail entre ces threads. À mesure que la charge de travail augmente ou diminue, la classe tourne ou détruit plus de threads pour s'adapter à la charge de travail.

Si la charge de travail est plus importante et que le célibataire HandlerThreadne suffit pas, vous pouvez opter pourThreadPoolExecutor

Cependant, je voudrais avoir une connexion socket exécutée en service. Doit-il être exécuté dans un gestionnaire ou un thread, ou même une AsyncTask? L'interaction avec l'interface utilisateur n'est pas du tout nécessaire. Cela fait-il une différence en termes de performances que j'utilise?

Étant donné que l'interaction avec l'interface utilisateur n'est pas requise, vous ne pouvez pas y aller AsyncTask. Les threads normaux ne sont pas très utiles et sont donc HandlerThreadla meilleure option. Puisque vous devez maintenir la connexion de socket, le gestionnaire sur le thread principal n'est pas du tout utile. Créez un HandlerThreadet obtenez-en un à Handlerpartir du looper de HandlerThread.

 HandlerThread handlerThread = new HandlerThread("SocketOperation");
 handlerThread.start();
 Handler requestHandler = new Handler(handlerThread.getLooper());
 requestHandler.post(myRunnable); // where myRunnable is your Runnable object. 

Si vous souhaitez communiquer avec le thread d'interface utilisateur, vous pouvez utiliser un gestionnaire supplémentaire pour traiter la réponse.

final Handler responseHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            //txtView.setText((String) msg.obj);
            Toast.makeText(MainActivity.this,
                    "Foreground task is completed:"+(String)msg.obj,
                    Toast.LENGTH_LONG)
                    .show();
        }
    };

dans votre Runnable, vous pouvez ajouter

responseHandler.sendMessage(msg);

Plus de détails sur la mise en œuvre peuvent être trouvés ici:

Android: Toast dans un fil


5

À mon avis, les threads ne sont pas le moyen le plus efficace de faire des connexions de socket mais ils fournissent le plus de fonctionnalités en termes d'exécution de threads. Je dis cela parce que, par expérience, l'exécution de threads pendant une longue période entraîne des appareils très chauds et gourmands en ressources. Même un simple while(true)chauffera un téléphone en quelques minutes. Si vous dites que l'interaction avec l'interface utilisateur n'est pas importante, c'est peut-être une AsyncTaskbonne chose car elles sont conçues pour des processus à long terme. Ce n'est que mon avis là-dessus.

MISE À JOUR

Veuillez ignorer ma réponse ci-dessus! J'ai répondu à cette question en 2011, alors que j'étais beaucoup moins expérimenté dans Android que maintenant. Ma réponse ci-dessus est trompeuse et est considérée comme erronée. Je le laisse là parce que beaucoup de gens l'ont commenté ci-dessous en me corrigeant, et j'ai appris ma leçon.

Il y a de bien meilleures réponses sur ce sujet, mais je vais au moins me donner une réponse plus appropriée. Il n'y a rien de mal à utiliser un Java standard Thread; cependant, vous devez vraiment faire attention à la façon dont vous l'implémentez, car une mauvaise exécution peut être très gourmande en processeur (le symptôme le plus notable peut être le réchauffement de votre appareil). AsyncTasks sont assez idéales pour la plupart des tâches que vous souhaitez exécuter en arrière-plan (des exemples courants sont les E / S disque, les appels réseau et les appels de base de données). Cependant, les AsyncTasks ne doivent pas être utilisés pour des processus particulièrement longs qui peuvent devoir se poursuivre après que l'utilisateur a fermé votre application ou mis son appareil en veille. Je dirais que pour la plupart des cas, tout ce qui n'appartient pas au thread d'interface utilisateur peut être pris en charge dans un AsyncTask.


merci, y a-t-il réellement une raison pour laquelle je devrais utiliser des threads au lieu des AsyncTasks? Ou est-il plus recommandé de s'en servir?
Alx

9
@AeroDroid Dans votre exemple: "un simple moment (vrai)", vous fixerez le CPU ici, sauf si vous ajoutez un état de veille dans la boucle. Cela est vrai de toute boucle sans fin. Si vous souhaitez réduire l'utilisation du processeur en raison de cette surcharge, mettez le thread en veille pendant quelques millisecondes à la fin de la boucle.
Erreur 454

1
@Error 454 - c'est intéressant! Si vous deviez choisir un nombre approprié pour le temps de sommeil, serait-ce entre 40 et 80 millisecondes?
Abhijit

6
@Abhijit D'après le jeu que j'ai fait en SDL, il suffit d'ajouter un sommeil de 10 ms à la boucle pour passer de 99% du processeur à ~ 0 pendant les états inactifs.
Erreur 454

15
En fait, developer.android.com/reference/android/os/AsyncTask.html dit: "AsyncTasks devrait idéalement être utilisé pour les opérations COURTES". Vous devez également les utiliser avec précaution car ils peuvent être rejetés par le système sans exécution!
type-a1pha

5

AsyncTaskest conçu pour effectuer pas plus de quelques secondes d'opération à effectuer en arrière-plan (déconseillé pour les mégaoctets de téléchargement de fichiers à partir du serveur ou pour calculer une tâche intensive de processeur telle que les opérations d'E / S de fichiers). Si vous devez exécuter une opération de longue durée, il vous a été fortement conseillé d'utiliser des threads natifs java. Java vous propose différentes classes liées aux threads pour faire ce dont vous avez besoin. Utilisez Handlerpour mettre à jour le thread d'interface utilisateur.


2
public class RequestHandler {

    public String sendPostRequest(String requestURL,
                                  HashMap<String, String> postDataParams) {

        URL url;

        StringBuilder sb = new StringBuilder();
        try {
            url = new URL(requestURL);

            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(15000);
            conn.setConnectTimeout(15000);
            conn.setRequestMethod("POST");
            conn.setDoInput(true);
            conn.setDoOutput(true);


            OutputStream os = conn.getOutputStream();
            BufferedWriter writer = new BufferedWriter(
                    new OutputStreamWriter(os, "UTF-8"));
            writer.write(getPostDataString(postDataParams));

            writer.flush();
            writer.close();
            os.close();
            int responseCode = conn.getResponseCode();

            if (responseCode == HttpsURLConnection.HTTP_OK) {
                BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                sb = new StringBuilder();
                String response;
                while ((response = br.readLine()) != null){
                    sb.append(response);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    private String getPostDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
        StringBuilder result = new StringBuilder();
        boolean first = true;
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (first)
                first = false;
            else
                result.append("&");

            result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
            result.append("=");
            result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
        }

        return result.toString();
    }

}

1

Permettez-moi d'essayer de répondre à la question ici avec un exemple :) - MyImageSearch [Veuillez renvoyer l'image ici de l'écran d'activité principal - contenant un texte d'édition / bouton de recherche / vue de grille]

MyImageSearch

Description de MyImageSearch - Une fois que l'utilisateur entre les détails dans le champ d'édition de texte et clique sur le bouton de recherche, nous rechercherons des images sur Internet via les services Web fournis par flickr (il vous suffit de vous y inscrire pour obtenir une clé / un jeton secret) - pour la recherche, nous envoyons une demande HTTP et récupérons les données JSON en réponse contenant les URL des images individuelles que nous utiliserons ensuite pour charger la vue de la grille.

Mon implémentation - Dans l'activité principale, je définirai une classe interne qui étend la tâche AsyncTask pour envoyer la demande HTTP dans la méthode doInBackGround et récupérer la réponse JSON et mettre à jour ma liste de tableaux locale de FlickrItems que je vais utiliser pour mettre à jour ma GridView via le FlickrAdapter (étend le BaseAdapter) et appelez l'adaptateur.notifyDataSetChanged () dans onPostExecute () d'AsyncTask pour recharger la vue de la grille. Notez qu'ici, la requête HTTP est un appel bloquant à cause duquel je l'ai fait via AsyncTask. Et, je peux mettre en cache les éléments dans l'adaptateur pour augmenter les performances ou les stocker sur SDCard. La grille que je vais gonfler dans le FlickrAdapter contient dans mon implémentation une barre de progression et une vue d'image. Ci-dessous, vous pouvez trouver le code de mainActivity que j'ai utilisé.

Réponse à la question maintenant - Donc, une fois que nous avons les données JSON pour récupérer des images individuelles, nous pouvons implémenter la logique de mise en arrière-plan des images via des gestionnaires ou des threads ou AsyncTask. Nous devons noter ici que puisque mes images une fois téléchargées doivent être affichées sur l'interface utilisateur / thread principal, nous ne pouvons pas simplement utiliser les threads tels quels car ils n'ont pas accès au contexte. Dans FlickrAdapter, les choix auxquels je pouvais penser:

  • Choix 1: Créez un LooperThread [étend le fil] - et continuez à télécharger des images séquentiellement dans un fil en gardant ce fil ouvert [looper.loop ()]
  • Choix 2: utilisez un pool de threads et publiez le runnable via myHandler qui contient une référence à mon ImageView, mais comme les vues dans Grid View sont recyclées, là encore le problème peut survenir lorsque l'image à l'index 4 est affichée à l'index 9 [le téléchargement peut prendre plus de temps]
  • Choix 3 [J'ai utilisé ceci]: utilisez un pool de threads et envoyez un message à myHandler, qui contient des données liées à l'index d'ImageView et à ImageView lui-même. l'image que nous avons essayé de télécharger.
  • Choix 4: utilisez AsyncTask pour télécharger les images en arrière-plan, mais ici, je n'aurai pas accès au nombre de threads que je veux dans le pool de threads et cela varie selon la version d'Android, mais dans le choix 3, je peux prendre une décision consciente de la taille du pool de threads en fonction de la configuration du périphérique utilisé.

Voici le code source:

public class MainActivity extends ActionBarActivity {

    GridView imageGridView;
    ArrayList<FlickrItem> items = new ArrayList<FlickrItem>();
    FlickrAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageGridView = (GridView) findViewById(R.id.gridView1);
        adapter = new FlickrAdapter(this, items);
        imageGridView.setAdapter(adapter);
    }

    // To avoid a memory leak on configuration change making it a inner class
    class FlickrDownloader extends AsyncTask<Void, Void, Void> {



        @Override
        protected Void doInBackground(Void... params) {
            FlickrGetter getter = new FlickrGetter();

            ArrayList<FlickrItem> newItems = getter.fetchItems();

            // clear the existing array
            items.clear();

            // add the new items to the array
            items.addAll(newItems);

            // is this correct ? - Wrong rebuilding the list view and should not be done in background
            //adapter.notifyDataSetChanged();

            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);

            adapter.notifyDataSetChanged();
        }

    }

    public void search(View view) {
        // get the flickr data
        FlickrDownloader downloader = new FlickrDownloader();
        downloader.execute();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

J'espère que ma réponse, bien que longue, aidera à comprendre certains des détails les plus fins.


Puis-je connaître la raison pour laquelle mon explication sur la base d'un exemple d'analogie a été rejetée, de sorte que j'en tire également des leçons?
akshaymani

2
tout d'abord merci pour votre réponse, même si ce sujet est un peu ancien, les concepts de base restent à jour. Ma question initiale n'a pas de réponse du tout, vous donnez un exemple et expliquez comment cela fonctionne, mais la question demande des différences entre le gestionnaire, l'asynctask et le thread.
Alx

@ 80leaves ok, je comprends maintenant, j'ai essayé d'expliquer comment je suis arrivé à la conclusion de choisir une voie plutôt qu'une autre. Quoi qu'il en soit, je serais ravi d'entendre vos / autres points de vue sur ce que j'ai écrit est correct ou s'il peut être encore amélioré.
akshaymani

1

Cela dépend lequel choisir en fonction de l'exigence

Le gestionnaire est principalement utilisé pour passer d'un autre thread au thread principal, le gestionnaire est attaché à un looper sur lequel il publie sa tâche exécutable dans la file d'attente. Donc, si vous êtes déjà dans un autre thread et passez au thread principal, vous devez gérer au lieu d'une tâche asynchrone ou d'un autre thread

Si le gestionnaire créé dans un thread autre que le thread principal qui n'est pas un boucleur ne donnera pas d'erreur lorsque le handle est créé le thread, ce thread doit être transformé en lopper.

AsyncTask est utilisé pour exécuter du code pendant quelques secondes qui s'exécute sur le thread d'arrière-plan et donne son résultat au thread principal ** * Limitations AsyncTask 1. La tâche Async n'est pas attachée au cycle de vie de l'activité et continue de s'exécuter même si son activité est détruite alors que le chargeur ne le fait pas 'ai pas cette limitation 2. Toutes les tâches asynchrones partagent le même thread d'arrière-plan pour l'exécution, ce qui a également un impact sur les performances de l'application

Le fil est également utilisé dans l'application pour le travail en arrière-plan, mais il n'a aucun rappel sur le fil principal. Si l'exigence convient à certains threads au lieu d'un thread et qui doivent exécuter la tâche plusieurs fois, l'exécuteur du pool de threads est la meilleure option.


0

Fil

Lorsque vous démarrez une application, un processus est créé pour exécuter le code. Pour utiliser efficacement les ressources informatiques, les threads peuvent être démarrés dans le processus afin que plusieurs tâches puissent être exécutées à la fois. Les threads vous permettent donc de créer des applications efficaces en utilisant efficacement le processeur sans temps d'inactivité.

Dans Android, tous les composants s'exécutent sur un seul thread principal appelé. Tâches de file d'attente du système Android et exécutez-les une par une sur le thread principal. Lorsque de longues tâches sont exécutées, l'application ne répond plus.

Pour éviter cela, vous pouvez créer des threads de travail et exécuter des tâches d'arrière-plan ou de longue durée.

Gestionnaire

Étant donné qu'Android utilise un modèle de thread unique, les composants d'interface utilisateur sont créés non sûrs, ce qui signifie que le thread qu'il a créé doit y accéder, ce qui signifie que le composant d'interface utilisateur doit être mis à jour uniquement sur le thread principal. Comme le composant d'interface utilisateur s'exécute sur le thread principal, les tâches qui s'exécutent sur les threads de travail ne peuvent pas modifier les composants d'interface utilisateur. C'est là que Handler entre en scène. Le gestionnaire à l'aide de Looper peut se connecter à un nouveau thread ou à un thread existant et exécuter le code qu'il contient sur le thread connecté.

Le gestionnaire permet la communication entre les threads. À l'aide de Handler, le thread d'arrière-plan peut lui envoyer des résultats et le gestionnaire connecté au thread principal peut mettre à jour les composants de l'interface utilisateur sur le thread principal.

AsyncTask

AsyncTask fourni par Android utilise à la fois le thread et le gestionnaire pour faciliter l'exécution de tâches simples en arrière-plan et la mise à jour des résultats du thread d'arrière-plan vers le thread principal.

Veuillez consulter les threads Android, les gestionnaires, les tâches asynctasques et les pools de threads pour des exemples.


-1

Handler- est un moyen de communication entre les threads. Dans Android, il est principalement utilisé pour communiquer avec le thread principal en créant et en envoyant des messages via le gestionnaire

AsyncTask- est utilisé pour exécuter des applications de longue durée dans un thread d'arrière-plan. Avec n, AsyncTaskvous pouvez effectuer l'opération dans un thread d'arrière-plan et obtenir le résultat dans le thread principal de l'application.

Thread- est un processus léger, pour atteindre la simultanéité et une utilisation maximale du processeur. Dans Android, vous pouvez utiliser le fil pour effectuer des activités qui ne touchent pas à l'interface utilisateur de l'application

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.