Android: quando dovrei usare un gestore () e quando dovrei usare un thread?


129

Quando ho bisogno di qualcosa da eseguire in modo asincrono , come un'attività di lunga durata o una logica che utilizza la rete, o per qualsiasi motivo, Avvio di un nuovo thread ed esecuzione funziona correttamente. Anche la creazione di un gestore e la sua esecuzione funzionano. Qual è la differenza? Quando dovrei usare ognuno? Quali sono i vantaggi / i motivi per usare a Handlere non a Thread?

PS. - Per amor di questa domanda, ignoriamo AsyncTask. - il Handler().postDelayedcaso d'uso mi è chiaro, per amor di questa domanda supponiamo che io abbia bisogno che l'attività inizi immediatamente.


Nella tua situazione, vai dritto e usa un nuovo thread, il mio prossimo suggerimento sarebbe AsyncTask, ma non è quello che vuoi chiaramente. I gestori vengono utilizzati principalmente se si desidera aggiungere un ritardo o un altro tipo di personalizzazione a un eseguibile.
kabuto178,

1
@Kabuto178 bene, ci sono altri vantaggi dei gestori che vale la pena ricordare che hai saltato. Ad esempio, essere in grado di interagire con il thread dell'interfaccia utente da un thread separato.
tony9099

Risposte:


168

Se qualunque cosa tu stia facendo è "pesante", dovresti farlo in un thread. Se non lo si avvia esplicitamente nel proprio thread, verrà eseguito sul thread principale (UI) che potrebbe essere evidente come interfaccia jittery o lenta nel rispondere agli utenti.

È interessante notare che quando si utilizza un thread è spesso utile utilizzare anche un gestore come mezzo di comunicazione tra il thread di lavoro che si sta avviando e il thread principale.

Una tipica interazione Thread / Handler potrebbe assomigliare a questa:

Handler h = new Handler(){
    @Override
    public void handleMessage(Message msg){
        if(msg.what == 0){
            updateUI();
        }else{
            showErrorDialog();
        }
    }
};

Thread t = new Thread() {
    @Override
    public void run(){
        doSomeWork();
        if(succeed){
            //we can't update the UI from here so we'll signal our handler and it will do it for us.
            h.sendEmptyMessage(0);
        }else{
            h.sendEmptyMessage(1);
        }
    }   
};

In generale, però, il take home è che dovresti usare un Thread ogni volta che stai facendo un lavoro che potrebbe essere di lunga durata o molto intenso (ad esempio qualsiasi rete, file IO, aritmica pesante, ecc.).


Grazie per la rapida risposta e la quantità di tempo investito (e la velocità della tua risposta !!)! Quindi, fammi vedere se ho ottenuto questo: Handler è progettato per facilitare la comunicazione non bloccante tra i thread di lavoro e il thread dell'interfaccia utente?
JRun,

3
@JRun Questo è uno degli usi sì. Controlla la descrizione del gestore nei documenti java per alcune fantastiche informazioni al riguardo. Compreso un altro dei suoi usi (per programmare messaggi e file eseguibili da eseguire come un punto in futuro).
Foamy Acquista il

ben spiegato @FoamyGuy!
tony9099,

Ciao, è garantito che updateUI()verrà eseguito dopo onCreateView(dopo aver caricato le nuove visualizzazioni)?
Zyoo,

1
Perché è message.what()? Non sarebbe solo if(msg == 0){? Grazie mille! :)
Ruchir Baronia,

64

Handler e Thread sono davvero 2 cose diverse.

È necessario creare un thread per eseguire lavori di lunga durata.

Un gestore è un oggetto molto conveniente per comunicare tra 2 thread (ad esempio: un thread in background deve aggiornare l'interfaccia utente. È possibile utilizzare un gestore per inviare un Runnable dal thread in background al thread dell'interfaccia utente).

Quindi non hai la scelta tra Handler o Thread. Usa un filo per fare lavori pesanti! (puoi usare un gestore se il tuo thread in background attiverà l'esecuzione di un lavoro in un altro thread - il più delle volte il thread dell'interfaccia utente)


Grazie per la rapida risposta e la quantità di tempo investito (e la velocità della tua risposta !!)!
JRun,

28

Handlere Threadsono due cose diverse, ma non si contraddicono a vicenda. Puoi avere a Handlere Threada allo stesso tempo e in realtà ognuno Handlerdeve essere in esecuzione in a Thread.

Per maggiori dettagli, potresti voler consultare questo articolo .

inserisci qui la descrizione dell'immagine


19

A Handlerviene eseguito sullo stesso Thread, a Threadviene eseguito su un thread diverso.

Utilizzare un gestore se è necessario eseguire qualcosa sullo stesso thread , in genere un elemento GUI o qualcosa del genere.

Usa un thread se vuoi mantenere libero il thread principale per fare altre cose . Usalo per tutto ciò che richiede una notevole quantità di tempo.


6
perché dovrei usare un gestore se voglio eseguire qualcosa sullo stesso thread? qual è lo scopo del metodo mHandler.post (...)?
Elias,

1
Elias, in tal caso, è possibile utilizzare il gestore se si desidera che una determinata attività venga eseguita dopo un determinato periodo di tempo o per ripetere un'attività ogni X tempo. Se non vuoi usare queste cose, hai ragione. è indegno usare un gestore. puoi semplicemente fare le cose della GUI proprio lì e poi, bcoz sei comunque nel thread dell'interfaccia utente, perché il gestore gira sul thread in cui è stato creato.
tony9099,

14

I gestori sono il modo migliore di comunicare tra lo sfondo e il thread dell'interfaccia utente. Generalmente i gestori sono associati alla coda dei messaggi di un thread e vengono utilizzati per inviare messaggi ed eseguibili al messaggio.

USO:

Discussione: per eseguire attività nel thread saperate (in background) rispetto al thread dell'interfaccia utente. (aiuta a sbloccare il thread dell'interfaccia utente)

Gestore Utilizzato per comunicare tra l'interfaccia utente e il thread in background.

Dai un'occhiata a questo articolo


4

Se è necessario aggiornare l'interfaccia utente da un nuovo thread, è necessario eseguire la sincronizzazione con il thread dell'interfaccia utente.

Per questo puoi usare la classe android.os.Handler o la classe AsyncTasks.

La classe Handler può aggiornare l'interfaccia utente. Un gestore fornisce metodi per ricevere istanze della classe Message o Runnable.

Il thread può inviare messaggi tramite il metodo sendMessage (Message msg) o tramite il metodo sendEmptyMessage ().

... maggiori informazioni qui sui thread ecc. (include i tutorial per i diversi meccanismi di threading e sincronizzazione e quando usare cosa)


Grazie per il tempo dedicato a rispondere alla mia domanda. Adoro il blog di Lars Vogel, è molto penetrante e facile da seguire. Grazie!
JRun,

2

Quali sono i vantaggi / i motivi per usare un gestore e non un thread?

Un gestore consente di inviare ed elaborare messaggi e Runnableoggetti associati a un thread MessageQueue. Ogni Handleristanza è associata a un singolo thread e alla coda dei messaggi di quel thread.

Quando si crea un nuovo Handler, viene associato alla coda thread / messaggi del thread che lo sta creando - da quel momento in poi, consegnerà i messaggi e i runnable a quella coda messaggi ed eseguirli quando escono dalla coda messaggi .

Esistono due usi principali per un gestore:

  1. Per programmare messaggi e Runnable da eseguire come punto futuro
  2. Per accodare un'azione da eseguire su un thread diverso dal vostro.

Se usi i thread Java, devi gestire qualcosa da solo: sincronizzare con il thread principale, cancellare un thread ecc.

Questo singolo thread non crea un pool di thread a meno che tu non usi ThreadPoolExecutoro ExecutorServiceAPI.

(Preso questa query dai tuoi commenti sulla risposta Blackbelt)

Perché non usare un Executor? e anche se volessi usare un Handler per farlo, come?

Riferimento: articolo sulle prestazioni del thread

Esistono alcuni tipi di lavoro che possono essere ridotti a compiti altamente paralleli e distribuiti. Con l'enorme volume di pacchetti di lavoro questo crea AsyncTaske HandlerThreadnon sono classi appropriate. La natura a thread singolo AsyncTasktrasformerebbe tutto il lavoro pool di thread in un sistema lineare. L'uso della HandlerThreadclasse, d'altra parte, richiederebbe al programmatore di gestire manualmente il bilanciamento del carico tra un gruppo di thread.

ThreadPoolExecutor è una classe di supporto per semplificare questo processo. Questa classe gestisce la creazione di un gruppo di thread, stabilisce le loro priorità e gestisce il modo in cui il lavoro viene distribuito tra quei thread. Man mano che il carico di lavoro aumenta o diminuisce, la classe gira o distrugge più thread per adattarsi al carico di lavoro.

 BlockingQueue workQueue= new LinkedBlockingQueue<Runnable>(100); // Work pool size
 ThreadPoolExecutor executor = new ThreadPoolExecutor(
            Runtime.getRuntime().availableProcessors(),       // Initial pool size
            Runtime.getRuntime().availableProcessors(),       // Max pool size
            1, // KEEP_ALIVE_TIME
            TimeUnit.SECONDS, //  KEEP_ALIVE_TIME_UNIT
            workQueue);

Puoi fare riferimento a questo articolo della guida per sviluppatori su create-threadpool per maggiori dettagli.

Dai un'occhiata a questo post per l'utilizzo di Handlereseguire più istanze eseguibili. In questo caso, tutte le Runnableattività verranno eseguite in un singolo thread.

Android: brindisi in un thread


1

Handlerpuò essere utilizzato insieme Threada per creare un meccanismo in coda. Puoi usare il handlerper pubblicare qualcosa sulThread Looper


Grazie per il tempo dedicato a rispondere alla mia domanda. Perché non usare un Executor? e anche se volessi usare un Handler per farlo, come?
JRun,

esecutore è un po 'diverso. Per usarlo devi estendere il thread e in esecuzione chiama static.metohd prepar.of della classe Looper. dopo aver chiamato il ciclo del metodo statico viene creata una coda ed è possibile utilizzare un ordine handlerbin per inoltrare le richieste e ottenere risultati indietro
Blackbelt
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.