Il contesto
Quando si parla di sviluppo su piattaforma Android si parla tipicamente di realizzare applicazioni basate su
componenti quali Activity
, Fragment
, Service
ed Intent. I componenti appena citati, tranne i service, gestiscono l'interfaccia utente e lavorano sul
thread main, ovvero il thread preposto alla gestione della user interface o UI.
Affrontiamo ora una situazione tipica: a fronte di un input da parte dell'utente, l'applicazione avvia un'attività
onerosa in termini di tempo e risorse mediante un thread in
background.
Al termine dell'operazione, si desidera che il termine dell'operazione venga segnalato mediante una notifica
visiva. L'esempio più classico di tale situazione è quella in
cui l'applicazione deve effettuare il download di risorse dal Web.
Il sequence diagram appena illustrato cerca di riassumere graficamente quanto spiegato. Da notare che
il service
e l'activity
vengono gestiti da thread
diversi. L'activity
avvia il service mediante degli intent
. Quando
il servizio in background termina, notifica l'avvenuta conclusione dei lavori mediante un altro intent
che
viene intercettato dall'activity
mediante un broadcast receiver
.
Nell'activity
l'avvio del servizio in background avviene mediante il codice:
Intent intent = new Intent(context, MyIntentService.class);
intent.setAction(ACTION_BAZ);
intent.putExtra(EXTRA_PARAM1, param1);
intent.putExtra(EXTRA_PARAM2, param2);
context.startService(intent);
Sempre nell'activity
la registrazione del broadcast receiver
:
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String message = intent.getStringExtra("message");
Log.d(TAG, "Ricevuto messaggio: " + message+" su thread "+Thread.currentThread().getName());
Snackbar.make(fab, "Termino processo in background", Snackbar.LENGTH_LONG).show();
txtMessage.setText(message);
}
};
Lato service il codice per notificare l'avvenuta fine dell'operazione in background:
private void handleActionBaz(String param1, String param2) {
Log.d(TAG, "BEGIN processo in background su thread "+Thread.currentThread().getName());
..
Intent intent = new Intent("intent-test");
intent.putExtra("message", "Operazione in background terminata!");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
L'esempio basato su Intent
e BroadcastReceiver
è abbastanza semplice. E' facile immaginare che
all'aumentare della complessità dell'applicazione
questo tipo di comunicazione inizi a rendere il codice e la struttura dei componenti poco leggibile e di
conseguenza difficile da mantenere.
EventBus: come semplificare la comunicazione tra componenti
Un modo per semplificare la comunicazione tra componenti è quello di utilizzare Event bus, una libreria Java
open source creata proprio per realizzare un bus di eventi a cui i vari componenti posso "agganciarsi" per ricevere
e spedire
eventi. Anche questa libreria si basa sull'uso di annotazioni e su un processore di annotazione per generare
il codice a supporto dell'applicazione.
EventBus consente di implementare un sistema di comunicazione tra componenti basati su eventi a cui questi
ultimi si possono collegare per "emettere" eventi
o per "sottoscrivere" messaggi. Sul sistema a bus possono esistere diversi tipi di eventi definiti
semplicemente da una classe.