Nota: tutte le informazioni di seguito sono disponibili sugli sviluppatori Android AsyncTask reference page. L'intestazione Utilizzo ha un esempio. Dai un'occhiata anche allo Painless Threading Android Developers Blog Entry.
Dai uno sguardo allo the source code for AsynTask.
La divertente notazione < >
consente di personalizzare l'attività Async. Le parentesi sono utilizzate per aiutare a implementare generics in Java.
Ci sono 3 parti importanti di un compito che è possibile personalizzare:
- Il tipo di parametri passati in - qualsiasi numero che si desidera
- Il tipo per quello che si utilizza per aggiornare la barra di avanzamento/indicatore
- il tipo per quello che il ritorno una volta finito con il compito di sfondo
E ricordate, che una di queste può essere interfacce. Ecco come puoi passare in più tipi sulla stessa chiamata!
Disponete i tipi di queste 3 cose nelle parentesi angolari:
<Params, Progress, Result>
Quindi, se avete intenzione di passare in URL
s e utilizzare Integers
per aggiornare i progressi e restituire un valore booleano che indica il successo si può scrivere:
public MyClass extends AsyncTask<URL, Integer, Boolean> {
in questo caso, se si sta scaricando Bitmap per esempio, si sarebbe gestendo ciò che si fa con le bitmap sullo sfondo. Si potrebbe anche solo restituire una HashMap di Bitmap se lo si desidera. Ricorda inoltre che le variabili membro che usi non sono limitate, quindi non sentirti troppo legato da parametri, progresso e risultato.
Per avviare un AsyncTask è necessario istanziarlo e quindi execute
in sequenza o in parallelo. Nell'esecuzione è dove passi le tue variabili. Puoi passarne più di uno.
Si noti che si non chiamare doInBackground()
direttamente. Questo perché così facendo si interrompe la magia di AsyncTask, ovvero che doInBackground()
viene eseguito in un thread in background. Chiamandolo direttamente così com'è, lo farebbe girare nel thread dell'interfaccia utente. Quindi, invece, dovresti usare un modulo di execute()
. Il lavoro di execute()
consiste nel dare il via allo doInBackground()
in un thread in background e non nel thread dell'interfaccia utente.
Lavorare con il nostro esempio dall'alto.
...
myBgTask = new MyClass();
myBgTask.execute(url1, url2, url3, url4);
...
onPostExecute
sparerà quando tutti i compiti da eseguire sono fatto.
myBgTask1 = new MyClass().execute(url1, url2);
myBgTask2 = new MyClass().execute(urlThis, urlThat);
Avviso come si può passare più parametri a execute()
che passa il parametro più a doInBackground()
. Questo è attraverso l'uso di String.format(...)
. Molti esempi mostrano solo l'estrazione dei primi parametri usando params[0]
, ma si dovrebbe make sure you get all the params. Se si sta passando in URL questo sarebbe (preso dall'esempio AsynTask, ci sono diversi modi per farlo):.
// This method is not called directly.
// It is fired through the use of execute()
// It returns the third type in the brackets <...>
// and it is passed the first type in the brackets <...>
// and it can use the second type in the brackets <...> to track progress
protected Long doInBackground(URL... urls)
{
int count = urls.length;
long totalSize = 0;
// This will download stuff from each URL passed in
for (int i = 0; i < count; i++)
{
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i/(float) count) * 100));
}
// This will return once when all the URLs for this AsyncTask instance
// have been downloaded
return totalSize;
}
Se avete intenzione di fare più attività bg, poi si vuole considerare che i suddetti myBgTask1
e myBgTask2
chiamate saranno effettuate in sequenza questo è grande se una chiamata dipende dall'altra, ma se le chiamate sono indipendenti, ad esempio si sta scaricando più i maghi, e non si cura quali arriva prima - allora si può fare i myBgTask1
e myBgTask2
chiamate in parallelo con il THREAD_POOL_EXECUTOR
:
myBgTask1 = new MyClass().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url1, url2);
myBgTask2 = new MyClass().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, urlThis, urlThat);
Nota:
Esempio
Ecco un esempio AsyncTask che può prendere tutti i tipi che vuoi sullo stesso comando execute()
.La limitazione è che ogni tipo deve implementare la stessa interfaccia:
public class BackgroundTask extends AsyncTask<BackgroundTodo, Void, Void>
{
public static interface BackgroundTodo
{
public void run();
}
@Override
protected Void doInBackground(BackgroundTodo... todos)
{
for (BackgroundTodo backgroundTodo : todos)
{
backgroundTodo.run();
// This logging is just for fun, to see that they really are different types
Log.d("BG_TASKS", "Bg task done on type: " + backgroundTodo.getClass().toString());
}
return null;
}
}
ora si può fare:
new BackgroundTask().execute(this1, that1, other1);
Dove ognuno di questi oggetti è un tipo diverso! (che implementa la stessa interfaccia)
probabilmente si dovrebbe vedere alcuni esempi e documentazione Android per questo per ottenere una migliore idea. –
Ho, il documento non dice nulla sul passare più oggetti su AsyncTask. –
Mi sono appena reso conto che dal momento che è una classe che probabilmente posso semplicemente creare membri pubblici e impostare quei membri a quello che voglio prima, '.execute()' ... Penso che funzionerà. –