一、为什么使用Handler

  当一个Activity运行的时候,会开启一条主线程,主线程主要负责处理与UI相关的事件,主线程不允许其他子线程操控它,更新UI界面。既然不允许我们在子线程中操控UI界面,那么,像我们平时所见的点击获取验证码,不断更新UI界面的操作又怎样实现的呢?这里就用到了我们的Handler消息传递的机制。

二、Handler消息传递机制介绍

Handler类的主要作用有两个:
1、在新启动的线程中发消息。
2、在主线程中获取、处理消息。
也就是线程发消息给主线程,在handler中存在一个MessageQueue(消息队列),线程的消息发给了MessageQueue,我们再通过Handler类中的handleMessage方法重写进行相关操作。Handler会不断的从MessageQueue中获取并处理消息。当然除了能从线程向主线程发消息,我们也可以从主线程向线程发消息,只是这种情况不常见,一般不会这样做。

补充

Handler 机制原理

三、使用实例

子线程向主线程发消息

1、开启一个新的线程,在新的线程中new一个Message,设置Message,并由发送Message
2、主线程中接收Handler,并进行UI的更新操作

package com.example.newjc;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity implements OnClickListener{
private Button mbtn_second;
private Handler handler=new Handler(){

@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case TIME_DESC:
String s=(String) msg.obj;
mbtn_second.setText(s);
break;

default:
break;
}


}


};
public static final int TIME_DESC=0x22;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mbtn_second=(Button) findViewById(R.id.bt_second);
mbtn_second.setOnClickListener(this);
}

@Override
public void onClick(View v) {

new Thread (new Runnable() {

@Override
public void run() {
int count=60;
while(count>0){
count--;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Message msg=new Message();
msg.obj=count+"秒";
msg.what=TIME_DESC;
handler.sendMessage(msg);
}

}
}).start();

}

}

Android 多线程编程:Handler消息传递机制—刷新UI主界面_ide


为了简化操作,我们对以上代码进行修改,采用递归思想来实现同样效果

注意:这里的代码并没有用到子线程,纯粹是handler的一种使用方式。

@Override
public void onClick(View v) {
count=60;
//发送一个空消息
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case TIME_DESC:
count--;
mbtn_second.setText(count + "秒");
if (count > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
handler.sendEmptyMessage(TIME_DESC);
}
break;
default:
break;
}
}
};

主线程给子线程发消息

public class MainActivity extends Activity implements OnClickListener
private Button mbtn_second;
private Button mbtn_second2;
private int count;
private Mythread thread;
public static final int TIME_DESC = 0x22;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mbtn_second = (Button) findViewById(R.id.bt_second);
mbtn_second2 = (Button) findViewById(R.id.bt_second2);
mbtn_second.setOnClickListener(this);
mbtn_second2.setOnClickListener(this);
}

@Override
public void onClick(View v) {
//count = 60;
//handler.sendEmptyMessage(TIME_DESC);
switch (v.getId()) {
case R.id.bt_second:
thread=new Mythread();
thread.start();
break;
case R.id.bt_second2:
//因为handler需要时间创建,因此不能直接将下面的代码放在 //thread.start();下面,放在他下面会报空指针

thread.handler.sendEmptyMessage(0);
break;
default:
break;
}

// thread.handler.sendEmptyMessage(0);
}
class Mythread extends Thread{
private Handler handler;
@Override
public void run() {
//handler—send-MessageQueue-looper读取—hangleMessage操作
//looper是主线程中默认使用,因此在子线程向主线程发消息的时候没有添加
//但是子线程不具有,因此必须写出
Looper.prepare();
handler=new Handler(){
@Override
public void handleMessage(Message msg) {
Log.d("主线程给子线程", "主线程给子线程");
}
};
Looper.loop();
}
}
}