2013-08-21 33 views
5

Ho un dubbio sulla possibilità di ripetere un AsyncTask in un'applicazione per Android. Vorrei ripetere alcune operazioni, ad esempio il download di un file da un server, n volte se per qualche motivo è impossibile scaricare il file. C'è un modo rapido per farlo?Ripeti AsyncTask

+1

Qual è esattamente il problema? È possibile avviare nuovamente lo stesso AsyncTask in caso di errore. –

+0

utilizza la classe di servizio e alaram manager per la ripetizione dell'attività asincrona – Mohit

risposta

8

Non è possibile ripetere un AsyncTask ma è possibile ripetere le operazioni eseguite.

Ho creato questa piccola classe di supporto che è possibile estendere al posto di AsyncTask, l'unica grande differenza è che si utilizzerà repeatInBackground anziché doInBackground e che onPostExecute avrà un nuovo parametro, l'eventuale eccezione generata.

Tutto ciò che si trova in repeatInBackground verrà ripetuto automaticamente fino a quando il risultato è diverso da null/eccezione non viene generata e ci sono stati meno di maxTries.

L'ultima eccezione generata all'interno del ciclo verrà restituita in onPostExecute (Risultato, Eccezione).

È possibile impostare i tentativi max utilizzando il costruttore RepeatableAsyncTask (int retries).

public abstract class RepeatableAsyncTask<A, B, C> extends AsyncTask<A, B, C> { 
    private static final String TAG = "RepeatableAsyncTask"; 
    public static final int DEFAULT_MAX_RETRY = 5; 

    private int mMaxRetries = DEFAULT_MAX_RETRY; 
    private Exception mException = null; 

    /** 
    * Default constructor 
    */ 
    public RepeatableAsyncTask() { 
     super(); 
    } 

    /** 
    * Constructs an AsyncTask that will repeate itself for max Retries 
    * @param retries Max Retries. 
    */ 
    public RepeatableAsyncTask(int retries) { 
     super(); 
     mMaxRetries = retries; 
    } 

    /** 
    * Will be repeated for max retries while the result is null or an exception is thrown. 
    * @param inputs Same as AsyncTask's 
    * @return Same as AsyncTask's 
    */ 
    protected abstract C repeatInBackground(A...inputs); 

    @Override 
    protected final C doInBackground(A...inputs) { 
     int tries = 0; 
     C result = null; 

     /* This is the main loop, repeatInBackground will be repeated until result will not be null */ 
     while(tries++ < mMaxRetries && result == null) { 
      try { 
       result = repeatInBackground(inputs); 
      } catch (Exception exception) { 
       /* You might want to log the exception everytime, do it here. */ 
       mException = exception; 
      } 
     } 
     return result; 
    } 

    /** 
    * Like onPostExecute but will return an eventual Exception 
    * @param c Result same as AsyncTask 
    * @param exception Exception thrown in the loop, even if the result is not null. 
    */ 
    protected abstract void onPostExecute(C c, Exception exception); 

    @Override 
    protected final void onPostExecute(C c) { 
     super.onPostExecute(c); 
     onPostExecute(c, mException); 
    } 
} 
+0

Funziona come una classe statica? Mi piace usare AsyncTask statici per evitare il riferimento ciondolante durante un cambio di orientamento. Sai se la tua classe lavora in modo statico? –

+0

Lo uso sempre in modo statico. –

1

Non è possibile riutilizzare lo stesso AsyncTask oggetto come, according to the AsyncTask Docs

L'attività può essere eseguito solo una volta (un'eccezione verrà generata se una seconda esecuzione è tentato.)

Ma puoi creare comunque molti nuovi oggetti di quella classe di cui hai bisogno all'interno di un ciclo. Tuttavia, un modo migliore per eseguire l'operazione di download n numero di volte all'interno del tuo doInBackground().

Se questo non risponde alla tua domanda quindi si prega di essere più specifico per quanto riguarda il problema

0

ho fatto in quel modo. Può provare e provare fino a (cerca == MAX_RETRY) o il risultato non è nullo. Un codice leggermente modificato dalla risposta accettata, meglio per me.

private class RssReaderTask extends AsyncTask<String, Void, ArrayList<RssItem>> { 

    // max number of tries when something is wrong 
    private static final int MAX_RETRY = 3; 

    @Override 
    protected ArrayList<RssItem> doInBackground(String... params) { 

     ArrayList<RssItem> result = null; 
     int tries = 0; 

     while(tries++ < MAX_RETRY && result == null) { 
      try { 
       Log.i("RssReaderTask", "********** doInBackground: Processing... Trial: " + tries); 
       URL url = new URL(params[0]); 
       RssFeed feed = RssReader.read(url); 
       result = feed.getRssItems(); 
      } catch (Exception ex) { 
       Log.i("RssReaderTask", "********** doInBackground: Feed error!"); 
      } 
     } 

     return result; 
    } 

    @Override 
    protected void onPostExecute(ArrayList<RssItem> result) { 
     // deal with result 
    } 

}