DevCorner: utilizziamo il pattern Observer

Giuseppe Tripodi
Giuseppe Tripodi Tech Master
DevCorner: utilizziamo il pattern Observer

Se volete fare della programmazione il vostro lavoro (o per lo meno il vostro passatempo!), prima o poi verrete a contatto con quelli che - ad un primo momento - potrebbero sembrare una bestia nera: i Design Pattern.
Come suggerisce Wikipedia, si tratta di "soluzioni progettuali generali a problemi ricorrenti": non sono legati ad un particolare linguaggio di programmazione e non sono, di conseguenza, vincolati da una determinata sintassi. Si tratta, in soldoni, di "processi logici" ormai assodati con cui risolvere delle problematiche comuni nella programmazione.
Uno dei più utili che incontrerete (nonché uno che userete di frequente) è l'Observer. Vediamo, quindi, un semplicissimo esempio di come utilizzarlo su Android.

L'Observer, come ci suggerisce sempre la cara Wikipedia

definisce una dipendenza uno a molti fra oggetti diversi, in maniera tale che se un oggetto cambia il suo stato, tutti gli oggetti dipendenti vengono notificati del cambiamento avvenuto e possono aggiornarsi.

Volendo banalizzare, se la madre di Pierino chiede a suo figlio di andare a comprare delle uova per fare una frittata, probabilmente la povera donna resterà in attesa del ritorno del figlio per preparare la cena; nel frattempo potrà fare altro (spolverare casa, conquistare la Kamchatcha), ma non appena il docile Pierino le "notificherà" di essere rientrato, la madre inizierà i suoi processi per una frittatona di cipolle come si deve.

Facendo un esempio più concreto, di recente mi è capitato di dover riempire una ListView customizzata con degli elementi prelevati da un oggetto, provenienti da un un server esterno: in questo caso, ovviamente, finché il client HTTP non avrà terminato il download sarà impossibile riempire la lista con foto e testi, per questo motivo ho voluto utilizzare un Observer ; inoltre, nel caso in cui l'oggetto venga modificato, la ListView si ripopolerà con glie elementi aggiornati.

L'esempio che vi propongo è ben più semplice di quello descritto su, ma rende l'idea in maniera semplice di come è possibile utilizzare in Android (o, meglio, in Java) questo Design Pattern. In quest'elementare app d'esempio, infatti, non faremo altro che istanziare una classe che, dopo 5 secondi d'attesa, notificherà alla MainActivity di "aver finito" e le passerà una stringa, che verrà utilizzata per un Toast (ovviamente il tempo in secondi serve solo per simulare possibili operazioni compiute in background).

All'interno del Layout abbiamo solo un bottone per avviare il processo, andiamo quindi a vedere subito un po' di codice: la nostra MainActivity implementa la solita interfaccia OnClickListener ma, a quest'ultima, si aggiunge Observer.
Dichiariamo quindi il nostro button, assegniamogli l'OnClickListener e facciamo in modo che, cliccando, venga creato un nuovo oggetto MyObserverClass, classe che andremo presto a creare. Al nostro oggetto, infine, assegniamo l'Observer che l'interfaccia ci ha forzato ad implementare, tramite il metodo update.

public class MainActivity extends Activity implements Observer, OnClickListener{

	Button start;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		start = (Button) findViewById(R.id.start);
		start.setOnClickListener(this);

	}

	@Override
	public void onClick(View v) {
		if(v.getId()==start.getId())
		{
			MyObserverClass myObserver = new MyObserverClass();
			myObserver.addObserver(this);
		}

	}
		@Override
	public void update(Observable observable, Object data) 
	{
		String s = (String) data;
		Toast.makeText(this, s, Toast.LENGTH_LONG).show();
	}
}

In quest'ultimo metodo, riceviamo un oggetto (che castiamo a Stringa) e lo mostriamo in un toast.

Abbiamo quindi finito la nostra classe "guardona", ma rimane da vedere cosa mettere all'interno di MyObserverClass: creiamo una nuova classe e facciamole estendere Observable (osservabile), dichiariamo un Handler (che utilizzeremo per "ritardare" la nostra azione) e nel costruttore richiamiamo il metodo createTost.

public class MyObserverClass extends Observable
{
	final Handler handler = new Handler();

	public MyObserverClass()
	{
		createTost();

	}

	private void createTost() 
	{
		handler.postDelayed(new Runnable() {
			  @Override
			  public void run() {
			    //Do something after 100ms

					triggerObservers();
			  }
			}, 5000);	

	}

Come potete vedere, tutto ciò che fa createToast() è richiamare a sua volta, dopo 5 secondi d'attesa, il metodo triggerObserver, con il quale verrà notificato alla MainActivity che le procedure da compiere sono state ultimate.
Non ci rimane, quindi che scrivere il suddetto metodo, che avrà la seguente forma "standard":

 private void triggerObservers() 
	 {
	        setChanged();
	        notifyObservers("Un saluto a tutti i lettori di AndroidWorld");
	  }

Il messaggio, ovviamente, è l'unica cosa che varia da un triggerObservers generico: una volta eseguito questo metodo, la nostra MainActivity si accorgerà che MyObserverClass ha terminato i "lavori" e, finalmente, mostrerà il Toast.


Speriamo che questa banale guida possa esservi utile per imparare ad utilizzare l'Observer e, in generale, per entrare nel mondo dei Design Pattern.
Come sempre trovate il codice completo tramite il nostro forum, dove potrete anche chiedere una mano d'aiuto qualora ne aveste bisogno: al prossimo martedì e buon sviluppo a tutti!

Via: DevCorner