2012-01-18 8 views
5

È un buon approccio avere uno HandlerThread in app per effettuare diverse azioni di spesa nel tempo, come, ad esempio, l'ordinamento o forse anche per lavorare con flussi di file/web? Cosa è meglio usare per tali scopi: diversi AsyncTask, diversi Thread s o uno HandlerThread come http://hi-android.info/src/android/webkit/WebViewWorker.java.html ?Cosa è meglio utilizzare diversi AsyncTask o HandlerThread (Thread pipeline)?

+0

Dalla mia esperienza, utilizzo AsyncTasks per tutto il lavoro del database. Una cosa buona è che, raggiungendo postExecute(), sai che il thread separato ha finito. Per attività che richiedono un lungo periodo di tempo (flusso/aggiornamenti dal Web) - Gestori o estendere direttamente la classe Thread. – hovanessyan

+0

Mi piace molto AsyncTask, ma per alcune versioni di Android, consente l'esecuzione di più thread in parallelo anziché in sequenza. Questo può portare a qualsiasi tipo di contesa per la bruttezza quando si lavora con i database. Stai attento là fuori. –

risposta

1

Risposta breve, sono tutti validi perché non si blocca l'interfaccia utente.

Risposta più lunga, Principalmente si riduce alle preferenze. La soluzione che utilizzo è una combinazione di thread di base e un gestore. Poiché un thread di base non viene eseguito sul thread dell'interfaccia utente principale, spesso quando si completa è necessario segnalare o aggiornare le impostazioni. Questo è quando uso un gestore e un set di chiavi facili da leggere. Permettendomi così di accedere a qualsiasi vista e cambiarla se necessario. Ricorda, non è saggio dichiarare e mantenere i riferimenti globali a Views, allocarli e usarli secondo le necessità e scartarli quando terminati.

private static final int SET_LOADING = 0; 
private static final int SET_TEXT  = 1; 


private Handler mEventHandler = new Handler() { 

    @Override 
    public void handleMessage(Message msg) { 
     // if stmts||switch - personal preference 
     if(msg.what  == SET_LOADING){ 

      setLoading(((Boolean) msg.obj)); 

     }else if(msg.what == SET_TEXT){ 

      setText(msg.arg1, (String) msg.obj); 

     } 
     super.handleMessage(msg); 
    } 
} 

/** 
* set the text of a textbox 
* @param id int - R.id.{...} 
* @param text String 
*/ 
private void setText(int id, String text){ 
    TextView t = ((TextView) findViewById(id)); 
    if(t != null){ 
     t.setText(text); 
    } 
} 


/** 
* is the UI currently loading something? lock controls 
* @param isLoading boolean 
*/ 
private void setLoading(boolean isLoading){ 
    mIsLoading = isLoading; 
    if(isLoading){ 
     (SomeSpinningProgressBar).setVisibility(View.VISIBLE); 
    }else{ 
     (SomeSpinningProgressBar).setVisibility(View.INVISIBLE); 
    } 
} 



public void onClick(View v) { 
    /** 
    * some button that triggers a database connection 
    */ 
    if(v.getId() == R.id.some_button) { 

     /** basic thread */ 
     new Thread(new Runnable() { 
       public void run() { 
        if(this.hasWebConnection()){ 
         /** tell the UI thread to start loading */ 
         mEventHandler.sendMessage(
          mEventHandler.obtainMessage(SET_LOADING, 0, 0, true)); 

         // do work... 

         if(someErrorOccuredBoolean){ 
          /** report to user of an error */ 
          mEventHandler.sendMessage(
           mEventHandler.obtainMessage(SET_TEXT, R.id.some_textview, 0, "There was an error!")); 
         } 
         /** tell the UI thread to stop loading */ 
         mEventHandler.sendMessage(
           mEventHandler.obtainMessage(SET_LOADING, 0, 0, false)); 
        }else{ 
         mEventHandler.obtainMessage(SET_TEXT, R.id.some_textview, 0, "No internet found!!")); 
        } 
       } 
      } 
     );  
    } 
} 
0

A volte, in particolare quando si utilizzano le librerie native, è necessario richiamare le funzioni sullo stesso thread utilizzato per l'inizializzazione della libreria. Il motivo è che la libreria può archiviare qualcosa nella memoria locale del thread. In questo caso, AsyncTask non è un'opzione.

Se le librerie di sistema utilizzano o meno l'archiviazione locale del thread e se verranno utilizzate o meno in futuro ... Bene, vedete il mio punto: per sicurezza, quando uso le librerie JNI, preferisci usare solo un thread, il che significa che non c'è AsyncTask -ing.

A proposito, poiché un thread di pipeline (noto anche come thread di gestione) esegue un'attività alla volta, devo utilizzare thread di gestori diversi per attività che possono essere eseguite in parallelo.

1

È necessario delegare un'operazione che richiede tempo (rete, accesso al database, ...) a un tipo di thread di lavoro. Non è accettabile bloccare il thread principale (UI).

AsyncTask è un oggetto di livello elevato. Si occupa della gestione dei thread e delle comunicazioni tra thread per te, utilizzando uno Handler interno e uno Executor. È stato progettato per il (molto) caso comune di fare qualcosa in background e spingere il risultato nell'interfaccia utente.

Utilizzando Handler e HandlerThread (o evento Thread) ti dà direttamente una maggiore flessibilità, al costo di un codice più complesso, e alcune insidie ​​sottili (per esempio How to Leak a Context: Handlers & Inner Classes).

Una scelta da fare è eseguire i compiti in serie o in parallelo. Un HandlerThread li serializzerebbe. Per AsyncTask dipende dalla versione di Android (ma questo può essere sovrascritto). La creazione di un numero Thread ogni volta può causare un numero eccessivo di thread simultanei.

Problemi correlati