Handler vs AsyncTask


128

Sono confuso su quando si scegliere AsyncTask su un gestore. Supponiamo di avere un codice che voglio eseguire ogni n secondi che aggiornerà l'interfaccia utente. Perché dovrei scegliere l'uno rispetto all'altro?


1
Questo è diventato più complicato con AsyncTaskLoaders. Consulta stackoverflow.com/q/7120813/969325 per maggiori informazioni.
Warpzit,

Risposte:


75

IMO, AsyncTask è stato scritto per fornire un modo comodo e facile da usare per ottenere l'elaborazione in background nelle app Android, senza preoccuparsi troppo dei dettagli di basso livello (thread, loop di messaggi ecc.). Fornisce metodi di callback che aiutano a pianificare le attività e anche ad aggiornare facilmente l'interfaccia utente quando richiesto.

Tuttavia, è importante notare che quando si utilizza AsyncTask, uno sviluppatore si sottomette alle sue limitazioni, risultanti dalle decisioni di progettazione prese dall'autore della classe. Ad esempio, ho scoperto di recente che esiste un limite al numero di lavori che possono essere programmati utilizzando AsyncTasks.

Handler è più trasparente dei due e probabilmente ti dà più libertà; quindi se vuoi un maggiore controllo sulle cose, scegli Handler, altrimenti AsynTask funzionerà perfettamente.


Giusto. Stavo usando AsyncTasks per tutte le operazioni in background nel mio progetto. Ad un certo punto ho iniziato a raggiungere quel limite massimo di posti di lavoro, quindi i miei compiti sarebbero iniziati solo dopo che un altro era finito. Alla fine ho dovuto cambiare tutta la mia struttura per smettere di usare gli asincctasks ed evitare di raggiungere quella limitazione.
tbraun

5
Da Honeycomb in poi, AsyncTasksvengono eseguiti su un thread, quindi nessun parallelismo più. Potresti ancora eseguirli su Executorun'implementazione parallela .
MrSnowflake,

63

La mia regola empirica sarebbe:

  • Se stai facendo qualcosa di isolato correlato all'interfaccia utente, ad esempio il download dei dati da presentare in un elenco, vai avanti e utilizza AsyncTask.

  • Se si stanno eseguendo più attività ripetute, ad esempio il download di più immagini che devono essere visualizzate ImageViews(come il download di miniature) al momento del download, utilizzare una coda di attività con Handler.


Il gestore si trova nel livello API 1 e ASYNCTASK nel livello API 3. sarà deprecato a tutti i costi? perché mi sto concentrando sul porting delle applicazioni dalle versioni precedenti alla 2.2 e 2.3 ..
yokks,

10
Nessuno dei due sarà deprecato in qualunque momento presto. Il gestore non sarà mai deprecato in quanto l'interfaccia utente è sostanzialmente costruita attorno ad essa.
alexanderblom,

Non dovresti usare un Caricatore per caricare i dati per la tua UI da presentare?
nbarraille,

19

Cerca sempre di evitare l'uso di AsyncTask quando possibile principalmente per i seguenti motivi:

  • Non è garantito il funzionamento di AsyncTask poiché esiste una base ThreadPool e una dimensione massima impostate dal sistema e, se si crea troppa asynctask, alla fine verranno distrutti

  • AsyncTask può essere terminato automaticamente, anche durante l'esecuzione, a seconda del ciclo di vita dell'attività e non si ha alcun controllo su di esso

  • I metodi AsyncTask in esecuzione sul thread dell'interfaccia utente, come onPostExecute, potrebbero essere eseguiti quando l'attività a cui si riferisce, non è più visibile o è probabilmente in uno stato di layout diverso, come dopo una modifica dell'orientamento.

In conclusione, non dovresti usare i metodi UIThread di AsyncTask, che è il suo principale vantaggio !!! Inoltre, dovresti fare solo lavori non critici su doInBackground. Leggi questa discussione per ulteriori approfondimenti su questi problemi:

AsyncTask è concettualmente difettoso o mi sto perdendo qualcosa?

Per concludere, prova a preferire l'uso di IntentServices, HandlerThread o ThreadPoolExecutor invece di AsyncTask quando uno dei problemi sopra citati può essere un problema per te. Sicuramente richiederà più lavoro ma l'applicazione sarà più sicura.


Sì, ho trascorso molto tempo a rimpiangere molti usi di AsyncTasks. Sembrano grandi, ma ... tanti problemi!
SMBiggs,

6
Mi dispiace postare così fortemente contro i tuoi punti, ma non posso lasciare che il tuo povero stile abbia effetti su Android. Punto uno. NON dovresti avere tanti thread in esecuzione. Se ti imbatti in questo la tua architettura è foobar. Punto 2. Come mai .. Okay, sì, tutto in Android è un gioco gratuito per il garbage collector ... Vedresti solo il comportamento di abserd come descritto sopra, in alcuni casi abusivi rigorosamente. Punto 3. Gestire il tuo compito, per non essere scortese, è un'abilità da principiante. O lo uccidi quando chiami onPause, oppure ti stacchi e attacchi correttamente di conseguenza.
StarWind0

1
vogella.com/tutorials/AndroidBackgroundProcessing/article.html Questo è tutto ciò che serve per imparare a fare correttamente le attività senza i problemi sopra (supponendo che non stai facendo qualcosa come vomitare qualche centinaio di attività)
StarWind0

16

Se vuoi fare un calcolo ogni x secondi, probabilmente dovresti pianificare a Runnablesu a Handler(con postDelayed()) e questo Runnabledovrebbe iniziare nel thread dell'interfaccia utente corrente. Se vuoi avviarlo in un altro thread, usa HandlerThread. AsyncTask è più facile da usare per noi ma non meglio del gestore.


7

Il gestore è associato al thread principale dell'applicazione. gestisce e pianifica i messaggi e i runnable inviati dai thread in background al thread principale dell'app.

AsyncTask fornisce un metodo semplice per gestire i thread in background al fine di aggiornare l'interfaccia utente senza bloccarla con operazioni che richiedono tempo.

La risposta è che entrambi possono essere utilizzati per aggiornare l'interfaccia utente da thread in background, la differenza sarebbe nello scenario di esecuzione. Si consiglia di utilizzare il gestore se si desidera inviare messaggi in ritardo o inviare messaggi a MessageQueue in un ordine specifico.

Puoi prendere in considerazione l'utilizzo di AsyncTask se desideri scambiare parametri (aggiornando così l'interfaccia utente) tra il thread principale dell'app e il thread in background in un modo semplice e conveniente.


3
Puoi creare il tuo gestore associato a un altro thread.
Aleksejs Mjaliks,

Il gestore non è necessariamente legato al thread principale (thread dell'interfaccia utente). È legato al thread in cui è stata istanziata e gestisce i messaggi o Runnable che arrivano a questa coda di messaggi del thread. Può anche inviare oggetti Message e Runnable a questa coda di messaggi del thread.
Azec-PDX il

2

AsyncTaskpresume che farai qualcosa sul thread dell'interfaccia utente, una volta terminato il lavoro in background. Inoltre, puoi eseguirlo solo una volta (dopo questo, il suo stato è FINISHEDe otterrai un'eccezione nel tentativo di eseguirlo ancora una volta). Inoltre, la flessibilità di utilizzo non è molto. Sì, puoi usarlo THREAD_POOL_EXECUTORper un'esecuzione parallela, ma lo sforzo potrebbe non essere degno.

Handlernon presume nulla, tranne la gestione di Runnables e Messaggi. Inoltre, può essere eseguito tutte le volte che vuoi . Sei libero di decidere a quale thread deve essere collegato, come comunica con altri gestori, magari producendoli HandlerThread. Quindi, è molto più flessibile e adatto per alcuni lavori ripetuti.

Controllare diversi tipi di Handleresempi qui .


0

Sono la migliore domanda per l'intervista che viene posta. AsyncTask : vengono utilizzati per scaricare il thread dell'interfaccia utente ed eseguire attività in background. Gestori : il Dosent Android ha un modo diretto di comunicazione tra l'interfaccia utente e il thread in background. I gestori devono essere utilizzati per inviare messaggi o eseguibili tramite la coda dei messaggi.

Pertanto, AsyncTasks viene utilizzato laddove sono necessarie attività da eseguire in background e Handlers vengono utilizzati per la comunicazione tra un'interfaccia utente e un thread in background.


0

doInBackground - fondamentalmente funziona in un altro thread. onPostExecute : pubblica i risultati sul thread dell'interfaccia utente e invia internamente un messaggio al gestore del thread principale. Il thread dell'interfaccia utente principale ha già associato un looper e un gestore.

Quindi, in pratica, se devi svolgere alcune attività in background, usa AsyncTask. Ma alla fine, se qualcosa deve essere aggiornato sull'interfaccia utente, utilizzerà il gestore del thread principale.

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.