Come usare il Bundle Android per Scambiare Dati tra Thread

La domanda a cui voglio rispondere con questo post è la seguente: Come usare il bundle Android per scambiare dati tra un tread in esecuzione ed il tread principale che gestisce l’interfaccia (UI)?

Questa situazione è abbastanza comune nei progetti Android e la soluzione è molto semplice ed immediata. Il contesto può essere il seguente:

  1. Una finestra Android (activity) crea un thread in background il quale esegue dei comandi
  2. Quest’ultimo thread, per esempio, ha bisogno di comunicare al thread chiamante (main UI) il risultato della computazione

La situazione può essere gestita usando una combinazione di messaggi Android ed Android bundle.

Il codice delle due classi Java coivolte in questo progetto sono le seguenti:

public class MainActivity extends Activity {

   private Thread workingthread = null;

   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      workingthread=new JobThread();
      workingthread.start();
    }
}

dove un Thread denominato workingthread è creato e il suo stato è messo in esecuzione quando l’evento onCreate viene innescato. La classe JobThread può essere dichiarata in questo modo:


public class JobThread extends Thread{
   public JobThread(){
    //constructor
   }
   public void run() {
     //do some work here
   }
}

La parte chiave di ogni thread Java è rappresentata dal metodo run(). Quest’ultimo viene invocato non appena il metodo start() della variabile workingthread viene eseguito. Supponiamo ora che la MainActivity abbia bisogno del risultato del risultato della computazione del background thread ed in particolare questo risultato è nella forma di una tripla di interi.

Per scambiare questa tripla con il thread dell’interfaccia utente (UI), Android permette di “impachettare” (da bundle) questo insieme di informazioni (creando quindi un oggetto con dati strutturati) e spedirlo al thread sorgente.

Per aggiungere valori (interi nel mio caso) al pacchetto bundle android, bisogna usare il metodo putInt assieme ad una chiave che identifica univocamente il dato appena impachettato. Una volta il pacchetto è stato creato ed i valori aggiungi, si può utilizzare il methodo sendMessage() per spedirlo al thread di destinazione. La chiave assegnata sarà utilizzata per estrarre dal pacchetto i dati di cui abbiamo bisogno.

L’attività MainActivity e la classe JobThread saranno:

public class MainActivity extends Activity {

	private Thread workingthread = null;

	//message handler of the main UI thread
	//the handler will be passed once the background thread is created
	//and it will be triggered once a message is received
	final Handler mHandler = new Handler(){

	  public void handleMessage(Message msg) {
	    Bundle b;
	    if(msg.what==1){

	    	b=msg.getData();

	    	//log the data received
	    	Log.d("data key 1", String.valueOf(b.getInt("k1")));
	    	Log.d("data key 2", String.valueOf(b.getInt("k2")));
	    	Log.d("data key 3", String.valueOf(b.getInt("k3")));

	    }
	    super.handleMessage(msg);
	  }
	};

	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		workingthread=new JobThread();
		workingthread.start(mHandler);
	}

}

public class JobThread extends Thread{

	private Handler hd;

	public JobThread(msgHandler){
		//constructor
		//store a reference of the message handler
		hd = msgHandler;
	}
	public void run() {
		//do some work here

		//create the bundle
		Bundle b = new Bundle(4);

		//add integer data to the bundle, everyone with a key
		b.putInt("key1", 4);
		b.putInt("key2", 7);
		b.putInt("key3", 91);

		//create a message from the message handler to send it back to the main UI
		Message msg = hd.obtainMessage();

		//specify the type of message
		msg.what = 1;

		//attach the bundle to the message
		msg.setData(b);

		//send the message back to main UI thread
		hd.sendMessage(msg);

	}
}

Android bundle e l’utilizzo di messaggi sono le tecniche che permettono di scambiare dati strutturati tra thread in esecuzione. Inoltre, questa tecnica è utilizzata per modificare gli elementi grafici dell’interfaccia di una applicazione Android direttamente da un thread in background.

Se ti è piaciuto l’articolo, per favore condividilo!