T#015 – Mostrare o bloccare l’avanzamento di un task eseguito in background con AsyncTask nelle nostre applicazioni android

Nel tutorial precedente abbiamo visto come gestire un caricamento di dati in background. L’esempio visto può essere ulteriormente migliorato, ad esempio aggiungendo un feedback durante il caricamento dei dati, che di fatto ci aiuterà a non far sembrare bloccata l’interfaccia della nostra applicazione. In questo nuovo tutorial di programmazione Android andremo a vedere nello specifico come implementare questa funzionalità e come aggiungere un button che interromperà, se premuto, il caricamento dei dati in background.

Feedback all’utente durante il caricamento

La classe che usiamo è sempre AsyncTask, rispetto all’esempio precedente cambiamo i generic usati. Non usiamo più il terzo generic Result (usiamo Void) ma valorizziamo con Application il secondo:

1
2
3
4
public class ApplicationAsyncTask extends AsyncTask<Void, Application, Void>
{
    //...
}

Il secondo parametro generic è quello usato per notificare un avanzamento del caricamento, nel nostro caso vogliamo aggiungere alla GridView un’applicazione alla volta ad ogni passo del ciclo principale. Per capire meglio analizziamo la nuova versione del metodo doInBackground:

1
2
3
4
5
6
7
8
9
protected Void doInBackground(Void... params)
{
	List<ResolveInfo> apps = Application.getAllInstalledApps(packageManager);
	for (ResolveInfo resolveInfo : apps)
	{
		publishProgress(new Application(resolveInfo, packageManager));
	}
	return null;
}

Ad ogni iterazione richiamiamo il metodo publishProgress sempre della classe AsyncTask. Questo metodo permette di eseguire un aggiornamento dell’interfaccia. Come già visto non è possibile aggiornare l’interfaccia grafica nel metodo doInBackground in quanto questo metodo viene eseguito in un thread in background.
L’oggetto che passiamo a publishProgress viene passato al metodo onProgressUpdate di AsyncTask:

1
2
3
4
5
6
7
protected void onProgressUpdate(Application... values)
{
	for (Application application : values)
	{
		mainActivity.applicationAdapter.add(application);
	}
}

Questo metodo viene eseguito nel thread principale e quindi può eseguire un aggiornamento dell’interfaccia principale. Nel nostro caso aggiungiamo l’applicazione che avevamo passato a publishProgress nell’adapter che contiene gli elementi da mostrare nella GridView.
Ma cosa sono quei tre punti fra il tipo e il nome del parametro passato al metodo onProgressUpdate? E’ un costrutto introdotto in Java 1.5 chiamato varargs, in pratica equivale a passare un array di oggetti. Per questo dentro il metodo eseguiamo un ciclo sul parametro values che è a tutti gli effetti un array di Application.
Il metodo onProgressUpdate (ma anche publishProgress) prende un varargs in modo da poter fare un aggiornamento parziale ogni n elementi invece che ogni elemento.

Cancellazione di un task in esecuzione

Vediamo adesso come aggiungere un button in basso all’interfaccia grafica per fermare il caricamento. Il metodo nella nostra activity richiamato da questo button è il seguente:

1
2
3
4
public void stop(View v)
{
	asyncTask.cancel(true);
}

In pratica il metodo stop della nostra activity richiama il metodo cancel dell’AsyncTask. Rispetto all’esempio precedente l’oggetto AsyncTask deve essere salvato in un campo della classe MainActivity e non in una variabile locale.
Chiamando il metodo cancel il thread in background non viene killato “brutalmente”, spetta a noi controllare periodicamente se l’esecuzione deve continuare. Nel nostro caso possiamo controllare a ogni iterazione chiamando il metodo isCancelled:

1
2
3
4
5
6
7
8
9
10
11
12
13
protected Void doInBackground(Void... params)
{
	List<ResolveInfo> apps = Application.getAllInstalledApps(packageManager);
	for (ResolveInfo resolveInfo : apps)
	{
		if (isCancelled())
		{
			return null;
		}
		publishProgress(new Application(resolveInfo, packageManager));
	}
	return null;
}

Nel caso in cui si prema il button per interrompere il caricamento il metodo onPostExecute non viene eseguito, al suo posto è possibile riscrivere il metodo onCancelled. In questo metodo possiamo notificare l’utente dell’avvenuta sospensione, nel nostro caso abilitiamo il button start e disabilitiamo quello di stop:

1
2
3
4
5
protected void onCancelled()
{
	mainActivity.stopButton.setEnabled(false);
	mainActivity.startButton.setEnabled(true);
}

Il risultato finale è una activity con due button in basso, il secondo permette di fermare il caricamento:

La scrittura del resto del codice (aggiungere il button nell’interfaccia e modificare l’activity) non l’abbiamo visto in dettaglio, se avete problemi potete comunque scaricare il progetto completo di Eclipse o contattarci via commento o meglio ancora tramite il nostro forum.
A presto!

By Fabio Collini

Da agosto 2009 sono un freelance android developer, ho rilasciato due applicazioni nell'Android Market: Apps Organizer e Folder Organizer. Presso OmniaGroup ricopro il ruolo di Tech Leader nell'ambito di un progetto di rich internet application che utilizza JSF, JPA(EclipseLink) ed EJB3.

2 comments

  1. Chrome mi informa che se proseguo nella navigazione del PRECEDENTE TUTORIAL rischio di beccarmi un virus

    1. Abbiamo avuto un problema negli scorsi giorni, che ora sembra risolto. Prova a svuotare la cache e facci sapere come va.. 😉

Leave a comment

Your email address will not be published.