Handler and Runnable
In the previous post, I have explained about the Handler and its uses. I have also provided a sample example for sending a message using handler to the UI thread from a helper thread. In this post. I will explained how to post a Runnable (Unit of work) to UI thread from a different thread inside a android application. A handler works like an mediator between the main UI thread and a background thread. It help to protect UI thread from direct manipulation by a background thread. It receives message from background thread and use the message to update the UI views. It post runnable to UI message queue to enqueue it.
A runnable can be posted using handler via three different methods defined inside the Handler class.
Post Method
When to use ?
post(Runnable)
Immediate post
postAtTime(Runnable, long)
Post at some fixed time in future
postDelayed(Runnable, long)
Delay of posting by time defined as 2nd
parameter
The first method will immediately push the runnable inside the MessageQueue of the main thread. 2nd method will hand the runnable at fixed time and 3rd method will delay the posting by the time given as second parameter of the 3rd method.
In the above picture, a background thread uses the Handler to post a runnable object ti the UI ,MessageQueue associated with the UI thread. In this scenario there is no exchange of message between Handler and Background thread.
An Example to post a Runnable using handler
Post Method
|
When to use ?
|
post(Runnable)
|
Immediate post
|
postAtTime(Runnable, long)
|
Post at some fixed time in future
|
postDelayed(Runnable, long)
|
Delay of posting by time defined as 2nd
parameter
|
In the example a background thread is generating random number periodically. This random number is used to inside the run method of the Runnable object. This runnable is posted on button click event to the MessageQueue immediately. The task inside the runnable is that it updates the random number value using a TextView widget.
So here first we define a Runnable that updates a random number TextView display. On clicking the button an event occurs which triggers the posting of the runnable object. In the 3rd step, this runnable is executed by the main thread and UI is updated accordingly. Below is the sample source code for the same.
MainActivity.java
package pp.handlerrunnable;
import java.util.Random;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
Random randm ;
Button start;
Button stop;
TextView rand;
private Handler myhandler = new Handler();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rand = (TextView)findViewById(R.id.random);
start = (Button)findViewById(R.id.start);
stop = (Button)findViewById(R.id.stop);
randm=new Random();
start.setOnClickListener(new Button.OnClickListener(){
@Override
public void onClick(View v) {
myhandler.post(randomTimedTask);
stop.setEnabled(true);
start.setEnabled(false);
}});
}
public void cancelHandler(View v){
myhandler.removeCallbacks(randomTimedTask);
start.setEnabled(true);
stop.setEnabled(false);
}
private Runnable randomTimedTask = new Runnable(){
@Override
public void run() {
int x = randm.nextInt(100);
rand.setText(String.valueOf(x));
myhandler.postDelayed(this, 1000);
}
};
}
package pp.handlerrunnable;
import java.util.Random;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
Random randm ;
Button start;
Button stop;
TextView rand;
private Handler myhandler = new Handler();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rand = (TextView)findViewById(R.id.random);
start = (Button)findViewById(R.id.start);
stop = (Button)findViewById(R.id.stop);
randm=new Random();
start.setOnClickListener(new Button.OnClickListener(){
@Override
public void onClick(View v) {
myhandler.post(randomTimedTask);
stop.setEnabled(true);
start.setEnabled(false);
}});
}
public void cancelHandler(View v){
myhandler.removeCallbacks(randomTimedTask);
start.setEnabled(true);
stop.setEnabled(false);
}
private Runnable randomTimedTask = new Runnable(){
@Override
public void run() {
int x = randm.nextInt(100);
rand.setText(String.valueOf(x));
myhandler.postDelayed(this, 1000);
}
};
}
|
activity_main.xml
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent"android:background="#f0fffa"android:orientation="vertical" ><TextViewandroid:id="@+id/textView1"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text="Handler with Runnable Test"android:textColor="#ff00"android:textSize="25sp"/><TextViewandroid:id="@+id/random"android:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_alignParentLeft="true"android:layout_below="@+id/textView1"android:layout_marginTop="64dp"android:text="Random Number !!!"android:background="#fffff9"android:textSize="25sp"android:textColor="#ff0000" /><Buttonandroid:id="@+id/start"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentLeft="true"android:layout_alignParentRight="true"android:layout_centerVertical="true"android:text="Generate Random Number"android:textStyle="bold"android:textSize="20sp" /><Buttonandroid:id="@+id/stop"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentLeft="true"android:layout_alignParentRight="true"android:layout_below="@+id/start"android:layout_marginTop="46dp"android:text="Stop Thread"android:onClick="cancelHandler"android:textStyle="bold"android:textSize="20sp" /></RelativeLayout> |
No comments:
Post a Comment