Threading in Android part 1: Handlers
Multi-Threading concept is essential in most platforms. it provides maximum
utilization of the processor. threading is used when the program executes
time consuming processes (such as calling a web service) and to give a
good user experience by unblocking the UI.
Android provides threading techniques to perform time consuming tasks in a
background thread with coordination with the UI thread to update the UI.
Android provides the following methods of threading:
When you create an object from the Handler class, it processes utilization of the processor. threading is used when the program executes
time consuming processes (such as calling a web service) and to give a
good user experience by unblocking the UI.
Android provides threading techniques to perform time consuming tasks in a
background thread with coordination with the UI thread to update the UI.
Android provides the following methods of threading:
- Handlers.
- Async. Tasks.
Messages and Runnable objects associated with the
current thread MessageQueue. the message queue holds the
tasks to be executed in FIFO (First In First Out) mannser. you will need
only ine Handler per activity where the background thread will
communicate with to update the UI.
The Handler is associated with the thread from which it's been created
We can communicate with the Handler by two methods:
- Messages.
- Runnable objects.
updating the text of a TextView using multiple threads.
Using Messages:
the steps of using a Handler are as follows:
- You create a Handler object with an asscociated callback
method to handle the received messages (it is the method where the UI update
will be done). - From the background thread you will need to send messages to the
handler.
public class MainActivity extends Activity {
TextView txt;
// our handler
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
//display each item in a single line
txt.setText(txt.getText()+"Item "+System.getProperty("line.separator"));
}
};
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
txt=(TextView)findViewById(R.id.txt);
}
@Override
protected void onStart() {
super.onStart();
// create a new thread
Thread background=new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<10;i++)
{
try {
Thread.sleep(1000); b.putString("My Key", "My Value:
"+String.valueOf(i));
// send message to the handler with the current message handler
handler.sendMessage(handler.obtainMessage());
} catch (Exception e) {
Log.v("Error", e.toString());
}
}
}
});
background.start();
}
}
each second a new line is written:
This example is pretty basic, it just sends the same message for a number of
times.
what if we want the message sent to hold data that's changed each time the
message is sent, the answer is to use Message.setData(Bundle bundle)
method by creating a Bundle object and adding the data to it like this:
public class MainActivity extends Activity {we put a string to the bundle and send a message with that bundle. in the
TextView txt;
// our handler
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// get the bundle and extract data by key
Bundle b = msg.getData();
String key = b.getString("My Key");
txt.setText(txt.getText() + "Item " + key
+System.getProperty("line.separator"));
}
};
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
txt = (TextView) findViewById(R.id.txt);
}
@Override
protected void onStart() {
super.onStart();
// create a new thread
Thread background = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
Message msg = new Message();
Bundle b = new Bundle();
b.putString("My Key", "My Value: " + String.valueOf(i));
msg.setData(b);
// send message to the handler with the current message handler
handler.sendMessage(msg);
} catch (Exception e) {
Log.v("Error", e.toString());
}
}
}
});
background.start();
}
}
handler method we receive the bundle and get the value with the predefined key.
after executing that code the text view would look like this:
Using Runnables:
another way to use Handlers is to pass them a Runnable by using the
Handler.post() method like this:
Runnable r=new Runnable() {
@Override
public void run() {
txt.setText("Runnable");
}
};
handler.post(r);
this will add the Runanble object to the message queue to be executed by
the handler.
Sending Messages in a
timely manner:
the following methods:
- handler.sendEmptyMessageAtTime(int what,long uptimeMillis):sends an
empty message at a specific time in milli-seconds, can be defined by using the
SystemClock.uptimeMillis() method to get the time since the device boot
in milli-seconds and concatinating to it. - handler.sendEmptyMessageDelayed(int what,long delayMillis):sends an
empty message after a certain amount of time in milli-seconds. - handler.sendMessageAtTime(Message msg,long uptimeMillis).
- handler.sendMessageDelayed(Message msg,long delayMillis).
- handler.postAtTime(Runnable r,long uptimeMillis).
- handler.postAtTime(Runnable r,Object token,long uptimeMillis):posts a
runnable with an object as a distinguishing token. - handler.postDelayed(Runnable r,long delayMillis).
runnable has been placed successfully in the message queue.
Removing Call backs:
use the following methods:
- handler.removeCallbacks(Runnable r).
- handler.removeCallbacks(Runnable r,Object token).
- handler.removeCallbacksAndMessages(Object token).
- handler.removeMessages(int what).
- handler.removeMessages(int what,Object object)
No comments: