Handler vs AsyncTask vs Thread [chiuso]


382

Mi sono un po 'confuso sulle differenze tra Handlers, AsyncTaske Threadsin Android. Ho letto alcuni blog e domande qui su StackOverflow.

Handlersono thread in background che ti forniscono la possibilità di comunicare con l'interfaccia utente. L'aggiornamento di una barra di avanzamento, ad esempio, dovrebbe essere effettuato tramite Handler. Usando i gestori hai il vantaggio di MessagingQueues, quindi se vuoi pianificare messaggi o aggiornare più elementi dell'interfaccia utente o hai attività ripetute.

AsyncTasksono simili, infatti, ne fanno uso Handler, ma non vengono eseguiti nel thread dell'interfaccia utente, quindi è utile per il recupero dei dati, ad esempio per il recupero di servizi Web. Successivamente puoi interagire con l'interfaccia utente.

Threadtuttavia non puoi interagire con l'interfaccia utente, fornire thread più "di base" e perdi tutte le astrazioni di AsyncTask.

Tuttavia, vorrei avere una connessione socket in esecuzione nel servizio. Questo dovrebbe essere eseguito in un gestore o in un thread o anche in un AsyncTask? L'interazione con l'interfaccia utente non è affatto necessaria. Fa la differenza in termini di prestazioni che utilizzo?

Nel frattempo, la documentazione è stata notevolmente migliorata.



9
"I gestori sono thread di background" - Anche alcune delle risposte più votate sembrano andare in quella direzione. Ma è un'idea sbagliata. A Handlernon è un thread e non esegue nulla. È solo un mezzo per passare in sicurezza i messaggi da un thread alla coda dei messaggi di un altro thread . Quindi, normalmente, devono essere ancora creati (almeno) due thread che possono quindi utilizzare un gestore, ma il gestore non può eseguire nulla da solo.
JimmyB,

Risposte:


57

Come dice il Tutorial sull'elaborazione in background di Android con Handlers, AsyncTask e Loaders sul sito Vogella:

La Handlerclasse può essere utilizzata per registrarsi su un thread e fornisce un semplice canale per inviare dati a questo thread.

La AsyncTaskclasse incapsula la creazione di un processo in background e la sincronizzazione con il thread principale. Supporta inoltre la segnalazione dell'avanzamento delle attività in esecuzione.

E a Threadè fondamentalmente l'elemento principale del multithreading che uno sviluppatore può utilizzare con il seguente svantaggio:

Se usi i thread Java devi gestire i seguenti requisiti nel tuo codice:

  • Sincronizzazione con il thread principale se si pubblicano risultati nell'interfaccia utente
  • Nessun valore predefinito per l'annullamento del thread
  • Nessun pool di thread predefinito
  • Nessun valore predefinito per la gestione delle modifiche alla configurazione in Android

E per quanto riguarda il AsyncTask, come afferma la Guida per gli sviluppatori Android :

AsyncTaskconsente un uso corretto e semplice del thread dell'interfaccia utente. Questa classe consente di eseguire operazioni in background e pubblicare risultati sul thread dell'interfaccia utente senza dover manipolare thread e / o gestori.

AsyncTaskè progettato per essere una classe di supporto intorno Threade Handler e non costituisce un quadro filettatura generica. AsyncTasks dovrebbe essere idealmente usato per operazioni brevi (al massimo pochi secondi). Se è necessario mantenere i thread in esecuzione per lunghi periodi di tempo, si consiglia vivamente di utilizzare le varie API fornite dal pacchetto java.util.concurrent come Executor, ThreadPoolExecutor e FutureTask.

Aggiornamento maggio 2015: ho trovato un'eccellente serie di lezioni su questo argomento.

Questa è la Ricerca Google: Douglas Schmidt tiene lezioni sulla concorrenza e la sincronizzazione Android

Questo è il video della prima lezione su YouTube

Tutto questo fa parte del CS 282 (2013): Programmazione di sistemi per Android della Vanderbilt University . Ecco la playlist di YouTube

Douglas Schmidt sembra essere un eccellente docente

Importante: se sei nel punto in cui stai pensando di utilizzare AsyncTaskper risolvere i tuoi problemi di threading, dovresti prima verificareReactiveX/RxAndroid un modello di programmazione forse più appropriato. Un'ottima risorsa per ottenere una panoramica è l' apprendimento di RxJava 2 per Android con l'esempio .


4
In quella serie di lezioni, questo link ti porterà direttamente ad alcuni esempi di thread: youtu.be/4Vue_KuXfCk?t=19m24s
Aggressor

353

Se guardiamo il codice sorgente, vedremo AsyncTasked Handlerè puramente scritto in Java. (Ci sono alcune eccezioni, però. Ma questo non è un punto importante)

Quindi non c'è magia in AsyncTasko Handler. Queste lezioni ci semplificano la vita come sviluppatore.

Ad esempio: Se il Programma A chiama il metodo A (), il metodo A () potrebbe essere eseguito in un thread diverso con il Programma A. Possiamo facilmente verificare con il seguente codice:

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

Perché dovremmo usare un nuovo thread per alcune attività? Puoi cercarlo su Google. Molte ragioni, ad esempio: sollevamento di lavori pesanti e di lunga durata.

Quindi, quali sono le differenze tra Thread, AsyncTaske Handler?

AsyncTaske Handlersono scritti in Java (internamente usano a Thread), quindi tutto ciò che possiamo fare con Handlero AsyncTask, possiamo ottenere usando Threadanche un .

Cosa può Handlere può AsyncTaskdavvero aiutare?

Il motivo più ovvio è la comunicazione tra il thread del chiamante e il thread di lavoro. ( Thread del chiamante : un thread che chiama il thread del lavoratore per eseguire alcune attività. Un thread del chiamante non deve necessariamente essere il thread dell'interfaccia utente). Naturalmente, possiamo comunicare tra due thread in altri modi, ma ci sono molti svantaggi (e pericoli) a causa della sicurezza dei thread.

Questo è il motivo per cui dovremmo usare Handlere AsyncTask. Queste classi svolgono la maggior parte del lavoro per noi, dobbiamo solo sapere quali metodi scavalcare.

La differenza tra Handlere AsyncTaskè: utilizzare AsyncTaskquando il thread del chiamante è un thread dell'interfaccia utente . Questo è ciò che dice il documento Android:

AsyncTask consente un uso corretto e semplice del thread dell'interfaccia utente. Questa classe consente di eseguire operazioni in background e pubblicare risultati sul thread dell'interfaccia utente senza dover manipolare thread e / o gestori

Voglio sottolineare due punti:

1) Facile utilizzo del thread dell'interfaccia utente (quindi, utilizzare quando il thread del chiamante è thread dell'interfaccia utente).

2) Non è necessario manipolare i gestori. (significa: è possibile utilizzare Handler anziché AsyncTask, ma AsyncTask è un'opzione più semplice).

Ci sono molte cose in questo post che non ho ancora detto, ad esempio: cos'è UI Thread o perché è più facile. Devi conoscere alcuni metodi dietro ogni classe e usarlo, capirai completamente il motivo.

@: quando leggi il documento Android, vedrai:

Il gestore consente di inviare ed elaborare oggetti Message e Runnable associati a MessageQueue di un thread

Questa descrizione all'inizio potrebbe sembrare strana. Dobbiamo solo capire che ogni thread ha ogni coda di messaggi (come un elenco di cose da fare), e il thread prenderà ogni messaggio e lo farà fino a quando la coda dei messaggi è vuota (proprio come finiamo il nostro lavoro e andiamo a letto). Pertanto, quando Handlercomunica, invia un messaggio al thread del chiamante e attenderà l'elaborazione.

Complicato? Basta ricordare che Handlerpuò comunicare in modo sicuro con il thread del chiamante.


4
in realtà asynctask si basa anche su handler e futuretask, vedi
Sumit

AsyncTask è essenzialmente una classe di supporto costruita su Handler e Thread. developer.android.com/reference/android/os/AsyncTask.html . Guarda il documento "AsyncTask è progettato per essere una classe di supporto per Thread e Handler". AsyncTask viene rilasciato in API3 mentre Handler esiste da API1.
hjchin,

52

Dopo aver guardato in profondità, è semplice.

AsyncTask:

È un modo semplice per usare un thread senza sapere nulla sul modello di thread java . AsyncTaskfornisce vari callback relativi al thread di lavoro e al thread principale.

Utilizzare per piccole operazioni di attesa come le seguenti:

  1. Recupero di alcuni dati dai servizi Web e visualizzazione sul layout.
  2. Query di database.
  3. Quando ti rendi conto che l'operazione in esecuzione non sarà mai, mai nidificata.

Handler:

Quando installiamo un'applicazione in Android, crea un thread per quell'applicazione chiamato MAIN UI Thread. Tutte le attività vengono eseguite all'interno di quel thread. Secondo la regola del modello di thread singolo Android, non possiamo accedere direttamente agli elementi dell'interfaccia utente (bitmap, visualizzazione di testo, ecc.) Per un altro thread definito all'interno di tale attività.

Un gestore consente di comunicare nuovamente con il thread dell'interfaccia utente da altri thread in background. Ciò è utile in Android poiché Android non consente ad altri thread di comunicare direttamente con il thread dell'interfaccia utente. Un gestore può inviare ed elaborare oggetti Message ed Runnable associati a MessageQueue di un thread. Ogni istanza del gestore è associata a un singolo thread e alla coda dei messaggi di quel thread. Quando viene creato un nuovo gestore, viene associato alla coda thread / messaggi del thread che lo sta creando.

È la soluzione migliore per:

  1. Ti permette di fare la coda dei messaggi.
  2. Pianificazione dei messaggi.

Thread:

Ora è il momento di parlare del thread.

Thread è il genitore di entrambi AsyncTaske Handler. Entrambi usano internamente thread, il che significa che è possibile anche creare il proprio modello di thread come AsyncTaske Handler, ma ciò richiede una buona conoscenza dell'implementazione multi-threading di Java .


1
AsyncTask api è, infatti, scritto con Futures, Handlers ed Executors. Vedi codice sorgente: grepcode.com/file_/repository.grepcode.com/java/ext/…
IgorGanapolsky

22

Viene AsyncTaskutilizzato per eseguire alcuni calcoli in background e pubblicare il risultato nel thread dell'interfaccia utente (con aggiornamenti di avanzamento opzionali). Dal momento che non sei interessato all'interfaccia utente, allora un Handlero Threadsembra più appropriato.

È possibile generare uno sfondo Threade passare i messaggi di nuovo al vostro thread principale utilizzando il Handler's postmetodo.


9

Filo

Android supporta i thread Java standard . È possibile utilizzare i thread standard e gli strumenti del pacchetto " java.util.concurrent" per mettere le azioni in background. L'unica limitazione è che non è possibile aggiornare direttamente l'interfaccia utente da un processo in background.

Se è necessario aggiornare l'interfaccia utente da un'attività in background, è necessario utilizzare alcune classi specifiche di Android. È possibile utilizzare la classe " android.os.Handler" per questo o la classe " AsyncTask"

handler

La classe " Handler" può aggiornare l'interfaccia utente. Un handle fornisce metodi per la ricezione di messaggi e per i file eseguibili. Per usare un gestore devi sottoclassarlo e sovrascriverlo handleMessage()per elaborare i messaggi. Per elaborare Runable, è possibile utilizzare il metodo post();È necessaria solo un'istanza di un gestore nella propria attività.

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

AsyncTask

Se si dispone di un dispositivo Activityche deve scaricare contenuto o eseguire operazioni che possono essere eseguite in background, AsyncTaskè possibile mantenere un'interfaccia utente reattiva e pubblicare i progressi per tali operazioni all'utente.

Per maggiori informazioni puoi dare un'occhiata a questi link.

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

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


6

Thread:

Puoi utilizzare il nuovo Threadper attività in background di lunga durata senza influire sul thread dell'interfaccia utente. Da Thread Java, non è possibile aggiornare il thread dell'interfaccia utente.

Poiché il thread normale non è molto utile per l'architettura Android, sono state introdotte classi di supporto per il threading.

Puoi trovare le risposte alle tue domande nella pagina della documentazione sulle prestazioni di threading .

Gestore :

A Handlerconsente 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.

Esistono due usi principali per un Handler:

  1. Pianificare i messaggi e i runnable da eseguire come punto futuro;

  2. Accodare un'azione da eseguire su un thread diverso dal proprio.

AsyncTask :

AsyncTaskconsente un uso corretto e semplice del thread dell'interfaccia utente. Questa classe consente di eseguire operazioni in background e pubblicare risultati sul thread dell'interfaccia utente senza dover manipolare thread e / o gestori.

svantaggi:

  1. Per impostazione predefinita, un'app AsyncTaskinserisce tutti gli oggetti che crea in un singolo thread. Pertanto, vengono eseguiti in modo seriale e, come nel thread principale, un pacchetto di lavoro particolarmente lungo può bloccare la coda. Per questo motivo, utilizzare AsyncTask per gestire oggetti di lavoro di durata inferiore a 5 ms .

  2. AsyncTaskgli oggetti sono anche i trasgressori più comuni per problemi di riferimento implicito. AsyncTaskgli oggetti presentano anche rischi relativi a riferimenti espliciti.

HandlerThread :

Potrebbe essere necessario un approccio più tradizionale all'esecuzione di un blocco di lavoro su un thread di lunga durata (a differenza di AsyncTask, che dovrebbe essere utilizzato per un carico di lavoro di 5 ms ) e una certa capacità di gestire manualmente quel flusso di lavoro. Un thread del gestore è effettivamente un thread di lunga durata che prende il lavoro da una coda e vi opera.

ThreadPoolExecutor :

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.

Se il carico di lavoro è maggiore e il singolo HandlerThreadnon è sufficiente, puoi procedereThreadPoolExecutor

Tuttavia, vorrei avere una connessione socket in esecuzione nel servizio. Dovrebbe essere eseguito in un gestore, in un thread o anche in un AsyncTask? L'interazione con l'interfaccia utente non è affatto necessaria. Fa la differenza in termini di prestazioni che utilizzo?

Dal momento che l'interazione con l'interfaccia utente non è richiesta, potresti non farlo AsyncTask. I thread normali non sono molto utili e quindi HandlerThreadè l'opzione migliore. Poiché è necessario mantenere la connessione socket, Handler sul thread principale non è affatto utile. Crea un HandlerThreade ottieni un Handlerdal looper di HandlerThread.

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

Se si desidera comunicare nuovamente al thread dell'interfaccia utente, è possibile utilizzare un altro gestore per elaborare la risposta.

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

nel tuo Runnable, puoi aggiungere

responseHandler.sendMessage(msg);

Maggiori dettagli sull'implementazione sono disponibili qui:

Android: brindisi in un thread


5

A mio avviso, i thread non sono il modo più efficiente di eseguire connessioni socket ma forniscono la maggior funzionalità in termini di esecuzione dei thread. Dico questo perché, per esperienza, eseguire i thread per lungo tempo fa sì che i dispositivi siano molto caldi e dispendiosi in termini di risorse. Anche un semplice while(true)riscalderà un telefono in pochi minuti. Se dici che l'interazione con l'interfaccia utente non è importante, forse AsyncTaskè buona perché sono progettate per processi a lungo termine. Questa è solo la mia opinione al riguardo.

AGGIORNARE

Si prega di ignorare la mia risposta di cui sopra! Ho risposto a questa domanda nel 2011, quando ero molto meno esperto in Android di quanto lo sia ora. La mia risposta sopra è fuorviante ed è considerata sbagliata. Lo lascio lì perché molte persone lo hanno commentato qui sotto correggendomi e ho imparato la mia lezione.

Ci sono altre risposte molto migliori su questo thread, ma almeno mi darò una risposta più corretta. Non c'è niente di sbagliato nell'usare un normale Java Thread; tuttavia, dovresti davvero fare attenzione a come lo implementi perché farlo in modo errato può richiedere molto processore (il sintomo più notevole può essere il riscaldamento del tuo dispositivo). AsyncTasksono piuttosto ideali per la maggior parte delle attività che si desidera eseguire in background (esempi comuni sono l'I / O del disco, le chiamate di rete e le chiamate al database). Tuttavia, AsyncTasks non dovrebbe essere usato per processi particolarmente lunghi che potrebbero dover continuare dopo che l'utente ha chiuso l'app o messo il dispositivo in standby. Direi che per la maggior parte dei casi, tutto ciò che non appartiene al thread dell'interfaccia utente, può essere curato in un AsyncTask.


grazie, c'è davvero un motivo per cui dovrei usare Thread invece di AsyncTasks? O è più consigliato usarlo?
Alx,

9
@AeroDroid Nel tuo esempio: "un semplice istante (vero)", inserirai qui la CPU a meno che non aggiungi uno stato di sospensione nel loop. Questo è vero per qualsiasi ciclo infinito. Se si desidera ridurre l'utilizzo della CPU a causa di questo sovraccarico, sospendere il thread per alcuni millisecondi alla fine del ciclo.
Errore 454

1
@Error 454 - è interessante! Se dovessi scegliere un numero appropriato per il tempo di sonno, sarebbe tra 40-80 millisecondi?
Abhijit,

6
@Abhijit Dalle cose di gioco che ho fatto in SDL, aggiungere semplicemente un sonno di 10 ms al loop è stato sufficiente per passare dal 99% della CPU a ~ 0 durante gli stati di inattività.
Errore 454

15
In realtà developer.android.com/reference/android/os/AsyncTask.html dice: "AsyncTasks dovrebbe idealmente essere usato per operazioni BREVI". Dovresti anche usarli con attenzione poiché possono essere eliminati dal sistema senza eseguire!
type-a1pha,

5

AsyncTaskè progettato per eseguire operazioni per non più di pochi secondi da eseguire in background (non consigliato per megabyte di download di file dal server o per calcolare attività intensive della CPU come operazioni di I / O file). Se è necessario eseguire un'operazione a esecuzione prolungata, si consiglia vivamente di utilizzare i thread nativi Java. Java ti offre varie classi relative ai thread per fare ciò di cui hai bisogno. Utilizzare Handlerper aggiornare il thread dell'interfaccia utente.


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

Vorrei provare a rispondere alla domanda qui con un esempio :) - MyImageSearch [Si prega di fare riferimento all'immagine qui della schermata principale dell'attività - contenente un testo di modifica / pulsante di ricerca / vista griglia]

MyImageSearch

Descrizione di MyImageSearch - Una volta che l'utente inserisce i dettagli nel campo di testo di modifica e fa clic sul pulsante di ricerca, cercheremo le immagini su Internet tramite i servizi web forniti da Flickr (devi solo registrarti per ottenere un token chiave / segreto) - per la ricerca inviamo una richiesta HTTP e RICEVIAMO i dati JSON in risposta contenente gli URL delle singole immagini che utilizzeremo per caricare la vista griglia.

La mia implementazione - Nell'attività principale definirò una classe interna che estende l'AsyncTask per inviare la richiesta HTTP nel metodo doInBackGround e recuperare la risposta JSON e aggiornare la mia ArrayList locale di FlickrItems che userò per aggiornare il mio GridView tramite FlickrAdapter (estende BaseAdapter) e chiama adapter.notifyDataSetChanged () in onPostExecute () di AsyncTask per ricaricare la vista griglia. Si noti che qui la richiesta HTTP è una chiamata bloccante a causa della quale l'ho eseguita tramite AsyncTask. Inoltre, posso memorizzare nella cache gli elementi nell'adattatore per aumentare le prestazioni o archiviarli su SDCard. La griglia che gonfierò in FlickrAdapter contiene nella mia implementazione una barra di avanzamento e una visualizzazione dell'immagine. Di seguito puoi trovare il codice per mainActivity che ho usato.

Rispondi alla domanda ora - Quindi, una volta che abbiamo i dati JSON per il recupero di singole immagini, possiamo implementare la logica di ottenere le immagini in background tramite Handlers o Thread o AsyncTask. Qui dovremmo notare che poiché le mie immagini una volta scaricate devono essere visualizzate sull'interfaccia utente / sul thread principale, non possiamo semplicemente usare i thread così come sono poiché non hanno accesso al contesto. In FlickrAdapter, le scelte che mi vengono in mente:

  • Scelta 1: Crea un LooperThread [estende il thread] - e continua a scaricare le immagini in sequenza in un thread mantenendo questo thread aperto [looper.loop ()]
  • Scelta 2: utilizzare un pool di thread e pubblicare il file eseguibile tramite myHandler che contiene riferimenti a my ImageView, ma poiché le visualizzazioni in Grid View vengono riciclate, il problema potrebbe ripresentarsi quando l'immagine nell'indice 4 viene visualizzata nell'indice 9 [il download può prenditi più tempo]
  • Scelta 3 [Ho usato questo]: utilizzare un pool di thread e inviare un messaggio a myHandler, che contiene i dati relativi all'indice di ImageView e ImageView stesso, quindi mentre eseguiamo handleMessage () aggiorneremo ImageView solo se currentIndex corrisponde all'indice di l'immagine che abbiamo provato a scaricare.
  • Scelta 4: Usa AsyncTask per scaricare le immagini in background, ma qui non avrò accesso al numero di thread che voglio nel pool di thread e varia con le diverse versioni di Android, ma in Scelta 3 posso prendere una decisione consapevole delle dimensioni del pool di thread in base alla configurazione del dispositivo utilizzata.

Ecco il codice sorgente:

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

Spero che la mia risposta, sebbene a lungo, possa aiutare a comprendere alcuni dei dettagli più fini.


Posso sapere il motivo per cui la mia spiegazione sulla base di un esempio per l'analogia è stata sottovalutata, così che anch'io possa imparare da essa?
akshaymani,

2
prima di tutto grazie per la tua risposta, anche se questo argomento è un po 'vecchio, i concetti chiave rimangono ancora aggiornati. Alla mia domanda iniziale non viene data risposta, stai dando un esempio e spieghi come funziona, ma le domande richiedono differenze tra gestore, asincrono e thread.
Alx,

@ 80leaves ok ora capisco il punto, ho provato a spiegare come sono arrivato alla conclusione di scegliere un modo rispetto all'altro. Ad ogni modo, mi piacerebbe sentire le tue opinioni su se ciò che ho scritto è corretto o se può essere ulteriormente migliorato.
akshaymani,

1

Dipende da quale scegliere è basato sul requisito

Il gestore viene utilizzato principalmente per passare da un altro thread al thread principale, il gestore è collegato a un looper su cui pubblica l'attività eseguibile in coda. Quindi, se si è già in un altro thread e si passa al thread principale, è necessario gestire anziché attività asincrona o altro thread

Se l'handler creato in un thread diverso da quello principale che non è un looper non genererà errori poiché handle viene creato il thread, quel thread deve essere trasformato in un lopper

AsyncTask viene utilizzato per eseguire il codice per alcuni secondi che viene eseguito sul thread in background e dà il risultato al thread principale ** * Limitazioni di AsyncTask 1. L'attività Async non è collegata al ciclo di vita dell'attività e continua a funzionare anche se la sua attività viene distrutta mentre il caricatore non lo fa non hanno questa limitazione 2. Tutte le attività asincrone condividono lo stesso thread in background per l'esecuzione che influiscono anche sulle prestazioni dell'app

Il thread viene utilizzato anche in app per il lavoro in background ma non ha alcuna richiamata sul thread principale. Se il requisito si adatta ad alcuni thread anziché a un thread e che devono essere assegnati più volte, allora l'esecutore del pool di thread è l'opzione migliore. Ad esempio Requisito di caricamento delle immagini da più URL come glide.


0

Filo

Quando si avvia un'app, viene creato un processo per eseguire il codice. Per utilizzare in modo efficiente le risorse di elaborazione, è possibile avviare thread all'interno del processo in modo da poter eseguire più attività contemporaneamente. Quindi i thread ti consentono di creare app efficienti utilizzando la CPU in modo efficiente senza tempi di inattività.

In Android, tutti i componenti vengono eseguiti su un singolo thread principale chiamato. Attività di coda del sistema Android ed eseguirle una ad una sul thread principale. Quando vengono eseguite attività con esecuzione prolungata, l'app non risponde.

Per evitare ciò, è possibile creare thread di lavoro ed eseguire attività in background o di lunga durata.

handler

Poiché Android utilizza un modello a thread singolo, i componenti dell'interfaccia utente vengono creati senza thread thread, il che significa che solo il thread creato deve accedervi, il che significa che il componente dell'interfaccia utente deve essere aggiornato solo sul thread principale. Poiché il componente dell'interfaccia utente viene eseguito sul thread principale, le attività eseguite sui thread di lavoro non possono modificare i componenti dell'interfaccia utente. Questo è dove Handler entra in scena. Il gestore con l'aiuto di Looper può connettersi al nuovo thread o thread esistente ed eseguire il codice che contiene sul thread collegato.

Il gestore rende possibile la comunicazione tra thread. Utilizzando Handler, il thread in background può inviare risultati e il gestore collegato al thread principale può aggiornare i componenti dell'interfaccia utente sul thread principale.

AsyncTask

AsyncTask fornito da Android utilizza sia thread che handler per semplificare l'esecuzione di semplici attività in background e l'aggiornamento dei risultati dal thread in background al thread principale.

Vedere esempi di thread, handler, asynctask e thread di android .


-1

Handler- è il mezzo di comunicazione tra i thread. In Android viene utilizzato principalmente per comunicare con il thread principale creando e inviando messaggi tramite gestore

AsyncTask- viene utilizzato per eseguire applicazioni a esecuzione prolungata in un thread in background. Con n AsyncTaskottieni puoi eseguire l'operazione in un thread in background e ottenere il risultato nel thread principale dell'applicazione.

Thread- è un processo leggero, per raggiungere la concorrenza e il massimo utilizzo della cpu. In Android puoi usare il thread per eseguire attività che non toccano l'interfaccia utente dell'app

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.