一、认识Looper和Handler对象
当主线程诞生时,就会去执行一个消息循环(Message Loop),以便持续监视它的消息队列(Message Queue简称MQ)。当UI事件发生了,通常会立即丢一个Message给MQ,此时主线程就立即从MQ里边取出该消息并处理。比如,用户在UI界面上按下一个Button按钮时,UI事件发生了,就会丢一些消息到MQ里,其中包括onClick消息,于是,主线程会及时从MQ取出onClick消息,然后调用Activity的onClick()函数去处理。处理完毕后,主线程又返回去继续执行消息循环,继续监视MQ,并一直循环下去,直到主线程的生命周期结束。通常是进程被删除时,主线程才会被删除。
Android里有一个Looper类,其对象里含有一个消息循环。也就是说,一个主线程有它自己专属的Looper对象,此线程诞生时,就会执行此对象里的消息循环。此外,一个主线程还会有其专属的MQ数据结构。
由于主线程会持续监视MQ的动态,所以在程序的任何函数,只要将消息丢入主线程的MQ里,就能与主线程通信了。
在Android,定义了一个Handler类,在程序的任何函数里,可以诞生Handler对象来将Message对象丢到MQ里,而与主线程通信。
在Android默认情况下,主线程诞生时,就会拥有自己的Looper对象和MQ数据结构。然而,主线程诞生子线程时,默认情况下,子线程并不具有自己的Looper和MQ。由于没有Looper对象,就没有消息循环(Message Loop),一旦工作完毕了,子线程就结束了,无法继续监视MQ,也就不需要MQ了。既然没有Looper对象也没有MQ,也就不能接受外部的Message对象了。则别的线程就无法透过MQ来传递消息给它了。
也就是说,如果别的线程(如主线程)需要跟子线程相互通信时,就必须替子线程诞生一个Looper对象和一个MQ数据结构,并通过Handler来发送和处理消息。
下面通过实例进一步掌握Handler和Looper的用法:
AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.misoo.pkxx"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".ac08"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
二、主线程丢消息给自己
public class ac01 extends Activity implements OnClickListener {
private Button btn0, btn1;
private Handler handler;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
btn0 = new Button(this);
btn0.setId(101);
btn0.setText("发送消息");
btn0.setOnClickListener(this);
btn1 = new Button(this);
btn1.setId(102);
btn1.setText("退出");
btn1.setOnClickListener(this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(135,
50);
params.topMargin = 10;
layout.addView(btn0, params);
layout.addView(btn1, params);
setContentView(layout);
handler = new Handler() {
public void handleMessage(Message msg) {
setTitle((String) msg.obj);
}
};
}
public void onClick(View v) {
switch (v.getId()) {
case 101:
handler.removeMessages(0);
Message message = handler.obtainMessage(1, 1, 1, "this is my message");
handler.sendMessage(message);
break;
case 102:
finish();
break;
}
}
}
三、子线程丢消息给主线程
public class ac02 extends Activity implements OnClickListener {
private Button btn0, btn1;
private Handler handler;
private Timer timer = new Timer();
private Integer k = 0;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
btn0 = new Button(this);
btn0.setId(101);
btn0.setText("发送消息");
btn0.setOnClickListener(this);
btn1 = new Button(this);
btn1.setId(102);
btn1.setText("退出");
btn1.setOnClickListener(this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(135,
50);
params.topMargin = 10;
layout.addView(btn0, params);
layout.addView(btn1, params);
setContentView(layout);
handler = new Handler() {
public void handleMessage(Message msg) {
setTitle((String) msg.obj);
}
};
}
public void onClick(View v) {
switch (v.getId()) {
case 101:
TimerTask timerTask = new TimerTask() {
public void run() {
handler.removeMessages(0);
Message message = handler.obtainMessage(
1,
1,
1,
Thread.currentThread().getName() + ":"
+ String.valueOf(k++));
handler.sendMessage(message);
}
};
timer.schedule(timerTask, 500, 1500);
break;
case 102:
finish();
break;
}
}
}
四、替子线程产生Looper和MQ
public class ac03 extends Activity implements OnClickListener {
private Thread thread = null;
private Button btn0, btn1, btn2;
private Handler handler;
private String string;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
btn0 = new Button(this);
btn0.setId(101);
btn0.setText("运行子线程");
btn0.setOnClickListener(this);
btn1 = new Button(this);
btn1.setId(102);
btn1.setText("显示内容");
btn1.setOnClickListener(this);
btn2 = new Button(this);
btn2.setId(103);
btn2.setText("退出");
btn2.setOnClickListener(this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(100,
50);
params.topMargin = 10;
layout.addView(btn0, params);
layout.addView(btn1, params);
layout.addView(btn2, params);
setContentView(layout);
thread = new Thread(new Task());
thread.start();
}
public void onClick(View v) {
switch (v.getId()) {
case 101:
Message msg = handler.obtainMessage(1, 33, 1, null);
handler.sendMessage(msg);
break;
case 102:
setTitle(string);
break;
case 103:
handler.getLooper().quit();
finish();
break;
}
}
class Task implements Runnable {
public void run() {
Looper.prepare();
handler = new Handler(){
public void handleMessage(Message msg) {
string = Thread.currentThread().getName() + ":"
+ String.valueOf(msg.arg1);
}
};
Looper.loop();
}
}
}
五、取得主线程的Looper
public class ac04 extends Activity implements OnClickListener {
private Thread thread;
private Button btn0, btn1;
private Handler handler;
private String string;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
btn0 = new Button(this);
btn0.setId(101);
btn0.setText("启动子线程");
btn0.setOnClickListener(this);
btn1 = new Button(this);
btn1.setId(102);
btn1.setText("退出");
btn1.setOnClickListener(this);
LayoutParams params = new LayoutParams(135, 50);
layout.addView(btn0, params);
layout.addView(btn1, params);
setContentView(layout);
thread = new myThread();
thread.start();
}
public void onClick(View v) {
switch (v.getId()) {
case 101:
Message msg = handler.obtainMessage(1, 33, 1, null);
handler.sendMessage(msg);
break;
case 102:
finish();
break;
}
}
class myThread extends Thread {
public void run() {
Looper.prepare();
handler = new Handler(getMainLooper()) {
public void handleMessage(Message msg) {
string = Thread.currentThread().getName() + ", value="
+ String.valueOf(msg.arg1);
setTitle(string);
}
};
Looper.loop();
}
}
}
六、取得子线程的Looper
public class ac05 extends Activity implements OnClickListener{
private Thread thread;
private Button btn0, btn1, btn2;
private Looper looper;
private String string;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
LayoutParams params = new LayoutParams(135, 60);
btn0 = new Button(this); btn0.setId(101);
btn0.setText("启动子线程"); btn0.setOnClickListener(this);
btn1 = new Button(this); btn1.setId(102);
btn1.setText("显示内容"); btn1.setOnClickListener(this);
btn2 = new Button(this); btn2.setId(103);
btn2.setText("退出"); btn2.setOnClickListener(this);
layout.addView(btn0, params);
layout.addView(btn1, params);
layout.addView(btn2, params);
setContentView(layout);
thread = new Thread(new myThread());
thread.start();
}
public void onClick(View v) {
switch(v.getId()){
case 101:
Handler handler = new Handler(looper){
public void handleMessage(Message msg) {
string = Thread.currentThread().getName()
+ ", value="
+ String.valueOf(msg.arg1);
}
};
Message msg = handler.obtainMessage(1, 33, 1, null);
handler.sendMessage(msg);
break;
case 102:
setTitle(string);
break;
case 103:
finish();
break;
}
}
class myThread extends Thread{
public void run() {
Looper.prepare();
looper = Looper.myLooper();
Looper.loop();
}
}
}
七、定义Handler子类别
public class ac06 extends Activity implements OnClickListener {
private Thread thread;
private Button btn0, btn1, btn2;
private Looper looper;
private String string;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
LayoutParams params = new LayoutParams(135, 60);
btn0 = new Button(this);
btn0.setId(101);
btn0.setText("启动子线程");
btn0.setOnClickListener(this);
btn1 = new Button(this);
btn1.setId(102);
btn1.setText("显示内容");
btn1.setOnClickListener(this);
btn2 = new Button(this);
btn2.setId(103);
btn2.setText("退出");
btn2.setOnClickListener(this);
layout.addView(btn0, params);
layout.addView(btn1, params);
layout.addView(btn2, params);
setContentView(layout);
thread = new Thread(new myThread());
thread.start();
}
public void onClick(View v) {
switch (v.getId()) {
case 101:
myHandler handler = new myHandler(looper);
Message msg = handler.obtainMessage(1, 33, 1, null);
handler.sendMessage(msg);
break;
case 102:
setTitle(string);
break;
case 103:
looper.quit();
finish();
break;
}
}
class myThread extends Thread {
public void run() {
Looper.prepare();
looper = Looper.myLooper();
Looper.loop();
}
}
class myHandler extends Handler{
public myHandler(Looper looper) {
super(looper);
}
public void handleMessage(Message msg) {
string = Thread.currentThread().getName()
+ ", value="
+ String.valueOf(msg.arg1);
}
}
}
八、主线程和子线程之间互传信息
public class ac07 extends Activity implements OnClickListener {
private Thread thread;
private Button btn0, btn1;
private int value = 0;
private Looper looper;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
btn0 = new Button(this);
btn0.setId(101);
btn0.setText("启动子线程");
btn0.setOnClickListener(this);
btn1 = new Button(this);
btn1.setId(102);
btn1.setText("退出");
btn1.setOnClickListener(this);
LayoutParams params = new LayoutParams(135, 50);
layout.addView(btn0, params);
layout.addView(btn1, params);
setContentView(layout);
thread = new myThread();
thread.start();
}
public void onClick(View v) {
switch (v.getId()) {
case 101:
subHandler handler = new subHandler(looper);
Message message = handler.obtainMessage(1, 33, 1, null);
handler.sendMessage(message);
break;
case 102:
looper.quit();
finish();
break;
}
}
class myThread extends Thread {
public void run() {
Looper.prepare();
looper = Looper.myLooper();
Looper.loop();
}
}
class mainHandler extends Handler {
public mainHandler() {
super(Looper.getMainLooper());
}
public void handleMessage(Message msg) {
setTitle(String.valueOf(msg.arg1));
}
}
class subHandler extends Handler {
public subHandler(Looper looper) {
super(looper);
}
public void handleMessage(Message msg) {
value = msg.arg1;
++value;
Handler handler = new mainHandler();
Message m = handler.obtainMessage(1, value, 1, null);
handler.sendMessage(m);
}
}
}
九、两个子线程之间互传信息
public class ac08 extends Activity implements OnClickListener {
private Thread thread1, thread2;
private Button btn0, btn1;
private int value = 0;
private Looper looper1, looper2;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
btn0 = new Button(this);
btn0.setId(101);
btn0.setText("启动子线程");
btn0.setOnClickListener(this);
btn1 = new Button(this);
btn1.setId(102);
btn1.setText("退出");
btn1.setOnClickListener(this);
LayoutParams params = new LayoutParams(135, 50);
layout.addView(btn0, params);
layout.addView(btn1, params);
setContentView(layout);
thread1 = new myThread1();
thread1.start();
thread2 = new myThread2();
thread2.start();
}
public void onClick(View v) {
switch (v.getId()) {
case 101:
t1Handler t1h = new t1Handler();
Message message = t1h.obtainMessage(1, 33, 1, null);
t1h.sendMessage(message);
break;
case 102:
looper1.quit();looper2.quit();
finish();
break;
}
}
class myThread1 extends Thread {
public void run() {
Looper.prepare();
looper1 = Looper.myLooper();
Looper.loop();
}
}
class myThread2 extends Thread {
public void run() {
Looper.prepare();
looper2 = Looper.myLooper();
Looper.loop();
}
}
class mainHandler extends Handler {
public mainHandler() {
super(Looper.getMainLooper());
}
public void handleMessage(Message msg) {
setTitle(String.valueOf(msg.arg1));
}
}
class t1Handler extends Handler {
public t1Handler() {
super(looper1);
}
public void handleMessage(Message msg) {
t2Handler t2h = new t2Handler();
Message message = t2h.obtainMessage(1, msg.arg1, 1, null);
t2h.sendMessage(message);
}
}
class t2Handler extends Handler {
public t2Handler() {
super(looper2);
}
public void handleMessage(Message msg) {
value = msg.arg1;
++value;
mainHandler mh = new mainHandler();
Message message = mh.obtainMessage(1, value, 1, null);
mh.sendMessage(message);
}
}
}
十、将Runnable对象丢到MQ
public class ac09 extends Activity implements OnClickListener{
private Thread thread;
private Button btn0, btn1;
private int value = 0;
private Looper looper;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
btn0 = new Button(this);
btn0.setId(101);
btn0.setText("启动子线程");
btn0.setOnClickListener(this);
btn1 = new Button(this);
btn1.setId(102);
btn1.setText("退出");
btn1.setOnClickListener(this);
LayoutParams params = new LayoutParams(135, 50);
layout.addView(btn0, params);
layout.addView(btn1, params);
setContentView(layout);
thread = new myThread();
thread.start();
}
public void onClick(View v) {
switch (v.getId()) {
case 101:
subHandler handler = new subHandler(looper);
Message message = handler.obtainMessage(1, 33, 1, null);
handler.sendMessage(message);
break;
case 102:
looper.quit();
finish();
break;
}
}
class myThread extends Thread {
public void run() {
Looper.prepare();
looper = Looper.myLooper();
Looper.loop();
}
}
class mainHandler extends Handler {
public mainHandler(Looper looper) {
super(looper);
}
public void handleMessage(Message msg) {}
}
class myRun implements Runnable{
public void run() {
setTitle(String.valueOf(value + 1));
}
}
class subHandler extends Handler {
public subHandler(Looper looper) {
super(looper);
}
public void handleMessage(Message msg) {
value += msg.arg1;
Handler handler = new mainHandler(Looper.getMainLooper());
Message m = handler.obtainMessage(1, value, 1, null);
handler.post(new myRun());
}
}
}