在Android中,Handler被用来提供用于线程间通信,以确保线程通信安全(比如UI线程的安全)。包含四个组成部分:Message,Looper,MessageQueue,Handler,这四个组成部分构成了多线程中经典的“生产者————消费者模型”
1、成员介绍
Message:主要功能是进行消息的封装,同时可以指定消息的操作形式;
Looper:消息循环泵,用来为一个线程跑一个消息循环。每一个线程最多只可以拥有一个。
MessageQueue:就是一个消息队列,存放消息的地方。每一个线程最多只可以拥有一个。
Handler:消息的处理者,handler 负责将需要传递的信息封装成Message,发送给Looper,继而由Looper将Message放入MessageQueue中。当Looper对象看到MessageQueue中含有Message,就将其广播出去。该handler 对象收到该消息后,调用相应的handler 对象的handleMessage()方法对其进行处理。
2、同线程各成员的关系及数量
①一个线程中只能有一个Looper,只能有一个MessageQueue,可以有多个Handler,多个Messge;
②一个Looper只能维护唯一一个MessageQueue,可以接受多个Handler发来的消息;
③一个Message只能属于唯一一个Handler;
④同一个Handler只能处理自己发送给Looper的那些Message;
本文将浅谈handler的两种用法:
①.post(Runnable)用法:
package mountain_hua.learn_handler1;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
//先在主线程中创建Handler,Handler会自动与主线程绑定
private Handler handler=new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
System.out.println("main thread id " + Thread.currentThread().getId());
test_handmessage();
}
public void test_handmessage(){
new Thread(){
@Override
public void run(){
//处理信息
try{
//模拟费时操作
System.out.println("run thread id " + Thread.currentThread().getId());
sleep(1000);
//这里使用Runnable
Runnable runnable=new Runnable() {
@Override
public void run() {
System.out.println("Runnable thread id " + Thread.currentThread().getId());
}
};
//这里执行post(Runnable)操作
handler.post(runnable);
}catch (Exception e){
e.printStackTrace();
}
}
}.start();
}
}
首先在主线程中创建了一个handler,这时handler会自动绑定主线程,然后在一个新线程里面创建了Runnable对象,并且用了handler的post(Runnable)操作来发送消息给在主线程中的handler执行。我们看看打印出来的结果:
07-30 21:34:23.891 21509-21509/mountain_hua.learn_handler1 I/System.out: main thread id 1
07-30 21:34:23.893 21509-21560/mountain_hua.learn_handler1 I/System.out: run thread id 9378
07-30 21:34:24.894 21509-21509/mountain_hua.learn_handler1 I/System.out: Runnable thread id 1
结果可以看到Runnable与main线程id相同,说明了Runnable里面执行的事件是被handler放在主线程中执行的,与Run所在线程无关 。
②.handleMessage用法:
package mountain_hua.learn_handler1;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
test_handmessage();
test_handmessage1();
}
public void test_handmessage(){
new Thread(){
@Override
public void run(){
//处理信息
try{
//模拟费时操作
System.out.println("run thread id " + Thread.currentThread().getId());
sleep(1000);
}catch (Exception e){
e.printStackTrace();
}
Message msg=new Message();
// 也可以用下面两种方法获得Message
// Message msg1=Message.obtain();
// Message msg2=handler.obtainMessage();
msg.what=0;//msg.what的类型是int型,作为msg的识别码
msg.arg1=1;//msg.arg1的类型是int型,可以传递简单的参数
msg.arg2=2;//msg.arg2的类型是int型,可以传递简单的参数
msg.obj="Object类型";//msg.obj是Object型,可以传递任意参数
//将Message发送给handler
handler.sendMessage(msg);
}
}.start();
}
public void test_handmessage1(){
new Thread(){
@Override
public void run(){
//处理信息
try{
//模拟费时操作
System.out.println("run thread id " + Thread.currentThread().getId());
sleep(2000);
}catch (Exception e){
e.printStackTrace();
}
Message msg=new Message();
// 也可以用下面两种方法获得Message
// Message msg1=Message.obtain();
// Message msg2=handler.obtainMessage();
msg.what=99;//msg.what的类型是int型,作为msg的识别码
msg.arg1=100;//msg.arg1的类型是int型,可以传递简单的参数
msg.arg2=101;//msg.arg2的类型是int型,可以传递简单的参数
msg.obj="Object类型";//msg.obj是Object型,可以传递任意参数
//将Message发送给handler
handler.sendMessage(msg);
}
}.start();
}
Handler handler=new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
System.out.println("handleMessage thread id " + Thread.currentThread().getId());
System.out.println("msg.arg1:" + msg.arg1);
System.out.println("msg.arg2:" + msg.arg2);
break;
case 99:
System.out.println("handleMessage thread id " + Thread.currentThread().getId());
System.out.println("msg.arg1:" + msg.arg1);
System.out.println("msg.arg2:" + msg.arg2);
}
}
};
}
这里用两个Messge给主线程中的Handler发送消息,打印出的信息为:
07-30 21:19:08.532 2461-2782/mountain_hua.learn_handler1 I/System.out: run thread id 9311
07-30 21:19:08.532 2461-2783/mountain_hua.learn_handler1 I/System.out: run thread id 9312
07-30 21:19:09.532 2461-2461/mountain_hua.learn_handler1 I/System.out: handleMessage thread id 1
07-30 21:19:09.532 2461-2461/mountain_hua.learn_handler1 I/System.out: msg.arg1:1
07-30 21:19:09.532 2461-2461/mountain_hua.learn_handler1 I/System.out: msg.arg2:2
07-30 21:19:10.532 2461-2461/mountain_hua.learn_handler1 I/System.out: handleMessage thread id 1
07-30 21:19:10.532 2461-2461/mountain_hua.learn_handler1 I/System.out: msg.arg1:100
07-30 21:19:10.532 2461-2461/mountain_hua.learn_handler1 I/System.out: msg.arg2:101
可以看到handler处理消息队列是在主线程中处理的(handler在哪个线程中创建的就与哪个线程绑定), 与run存在的线程无关。
参考资料:同一线程内多Handler使用浅析
Android中Handler的使用
深入源码解析Android中的Handler,Message,MessageQueue,Looper
android Handler机制原理 4个组成部分源码解析