The question that I want to answer with this post is the following: How bundle Android works for exchanging data from a running thread to the main UI?
This is a fairly common situation in Android projects and very simple to figure it out. The context might be the following:
- An Android activity that creates a thread running some work
- The created thread has to exchange some data with the main UI thread
This situation can be handled by using a combination of Android bundles and messages.
The code of the two Java classes involved in the project might be the following:
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(); } }
in which a Thread named workingthread is created and started on the onCreate lifecycle event. The JobThread might be declared as the following:
public class JobThread extends Thread{ public JobThread(){ //constructor } public void run() { //do some work here } }
The key part of every Java threads is the run() method. It is invoked once the start() method on the workingthread variable is called. Suppose the MainActivity needs the results of the computation done in the background thread. Indeed, suppose that the result is a triple of integers.
To figure this out, Android lets you use the data bundle (to create a rich object that contains structured data) and messages to send the data bundle back to the main UI thread.
To add (integer in my example) values to the bundle android, you should use the putInt method together with a key to “name” the data just created (so to retrieve them back). Once the bundle is created and the values added, you can use the sendMessage() method to send it back to the UI thread.
The resulting MainActivity and JobThread should look as:
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); } }
Bundle android and messages approach is interesting because it can be used both to send data back to the parent thread but also to update the main UI according to the values received. This is very useful because Android does not allow you to update graphical elements directly from background threads.
If you liked the article, please share it!
Pingback: Using bundle Android to exchange data between t...