在Android中应用到多线程通信,尤其是新的线程去更新主线程的UI,因为新线程无法直接更新widget, 所以在Android多应用handler处理多线程的通信。
Handler主要有两个作用,一是安排消息或者Runnable在某个主线程中某个地方执行,二是安排一个任务去别的线程工作。
提到Handler肯定会设计到Looper,Looper的作用就是替对应的Handler管理消息,每一个Handler都有一个属于自己的Looper,这是一个对一的关系,在Android中除了主线程外其他线程在使用时不会自动为handler分配Looper的,所以在新的线程应用Handler的时候必须首选Looper.prepare函数来初始化Looper,然后用loop()函数来做信息循环的处理。
MessageQueue是控制所属线程的消息,所有的message并不是直接会存储在MeesageQueue中,通过Looper工作的。MessageQueue, Looper
Handler三者是一对一的关系,并且他们三个和某一个所属的线程也是一对一的关系,每个线程都有自己的一套Handler机制 。
具体的消息运行机制是Looper将发出的消息放到MessageQueue中,然后循环的传递给Handler,Handler会将当前的Message进行处理,然后做出相应的反应。
其实无论怎样发送,他们的重点只是一条,用的哪个handler发送的消息,就由这个handler处理消息,这个线程所处的线程做出相应的反应。handler和thread是绑定的一对>一关系。 想让线程接收什么,就用线程所属的handler发送消息。
例如子线程给主线程发送消息更新UI 和主线程给子线程发送信息:
public class MainActivity extends Activity implements OnClickListener {
private MyHandler mHandler = null;
private Button btn1;
private TextView mText;
private HanderThread myThread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn1 = (Button) findViewById(R.id.button1);
mText = (TextView) findViewById(R.id.textview);
btn1.setOnClickListener(this);
mHandler = new MyHandler(Looper.getMainLooper());
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch(v.getId()){
case R.id.button1:
myThread = new HanderThread();
myThread.start();
}
}
class MyHandler extends Handler{
public MyHandler(Looper looper){
super(looper);
}
public void handleMessage(Message msg){
//此函数处理handler发送的消息。
switch(msg.what){
case 4:
String obj = msg.getData().getString("senddata");
mText.setText("receive "+obj);
break;
default:
break;
}
}
}
class HanderThread extends Thread{
HanderThread (){
}
public void run(){
// 在这里你可以做一些费时的操作,本例只是在这里发送了一个
//消息给主线程告诉它消息来自子线程,并改变TextView中的文字。
String msg = "from child thread";
Bundle mBundle = new Bundle();
Message Msg = mHandler.obtainMessage();
mBundle.putString("senddata",msg);
Msg.what = 4;
Msg.setData(mBundle);
//要记住这里发送这个message的是mHandler,这个handler是
//属于主线程的handler所以主线程来处理这个消息。并且有主线程
//来做出相应的改变。
mHandler.sendMessage(Msg);
}
}
public class MainActivity extends Activity {
private Handler mMainHandler = null;
private TextView info = null;
private Button msgBtn = null;
ChildThread child1 = null;
class ChildThread extends Thread {
private Handler childHander = null;
private String CHILD_TAG = "ChildThread";
public void run() {
this.setName("ChildThread");
// 初始化消息循环队列,需要在Handler创建之前
//必须用这个函数和loop(),否则报错。
Looper.prepare();
childHander = new Handler() {
@Override
public void handleMessage(Message msg) {
// 在子线程中可以做一些耗时的工作
String sMsg = "";
Message toMain = new Message();
// mMainHandler.obtainMessage();
toMain.obj = "This message from "
+ this.getLooper().getThread().getName()
+ " the main thread had sent " + (String) msg.obj;
// 这个消息是主线程的handler发送的,由主线程处理,这里
//主要是改变主线程TextView的文字。
mMainHandler.sendMessage(toMain);
}
};
//使消息开始循环。
Looper.loop();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
info = (TextView) findViewById(R.id.info);
msgBtn = (Button) findViewById(R.id.bt1);
mMainHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 处理收到的消息。
info.setText((String) msg.obj);
}
};
child1 = new ChildThread();
child1.start();
msgBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (child1.childHander != null) {
// 发送消息给子线程
Message childMsg = child1.childHander.obtainMessage();
Message msg = new Message();
msg.obj = mMainHandler.getLooper().getThread().getName()
+ " say hello";
// 因为发送这个小时的handler是子线程的所有子线程处理。
// 哪个线程处理消息要看是由属于哪个线程的handler发出的消息。
child1.childHander.sendMessage(msg);
}
}
});
}
}