Android单线程模型中Message、Handler、Message Queue、Looper之间的关系---附实例源码

四者之间的关系:
Handler获取当前线程中的looper对象,looper用来从存放Message的MessageQueue中取出Message,再有Handler进行Message的分发和处理.
简单定义:
1、Message Queue(消息队列):
用来存放通过Handler发布的消息,通常附属于某一个创建它的线程,可以通过Looper.myQueue()得到当前线程的消息队列. 
2、Handler:
可以发布或者处理一个消息或者操作一个Runnable,通过Handler发布消息,消息将只会发送到与它关联的消息队列,然也只能处理该消息队列中的消息. 3、Looper:
是Handler和消息队列之间通讯桥梁,程序组件首先通过Handler把消息传递给Looper,Looper把消息放入队列。Looper也把消息队列里的消息广播给所有的Handler:Handler接受到消息后调用handleMessage进行处理.
4、Message:
消息的类型,在Handler类中的handleMessage方法中得到单个的消息进行处理,在单线程模型下,为了线程通信问题,Android设计了一个Message Queue(消息队列), 线程间可以通过该Message Queue并结合Handler和Looper组件进行信息交换。
详细介绍:
1. Message
Message消息,理解为线程间交流的信息,处理数据后台线程需要更新UI,则发送Message内含一些数据给UI线程。
2. Handler
Handler处理者,是Message的主要处理者,负责Message的发送,Message内容的执行处理。后台线程就是通过传进来的 Handler对象引用来sendMessage(Message)。而使用Handler,需要implement 该类的 handleMessage(Message)方法,它是处理这些Message的操作内容,例如Update UI。通常需要子类化Handler来实现handleMessage方法。
3. Message Queue
Message Queue消息队列,用来存放通过Handler发布的消息,按照先进先出执行。
每个message queue都会有一个对应的Handler。Handler会向message queue通过两种方法发送消息:sendMessage或post。这两种消息都会插在message queue队尾并按先进先出执行。但通过这两种方法发送的消息执行的方式略有不同:通过sendMessage发送的是一个message对象,会被 Handler的handleMessage()函数处理;而通过post方法发送的是一个runnable对象,则会自己执行。
4. Looper
Looper是每条线程里的Message Queue的管家。Android没有Global的Message Queue,而Android会自动替主线程(UI线程)建立Message Queue,但在子线程里并没有建立Message Queue。所以调用Looper.getMainLooper()得到的主线程的Looper不为NULL,但调用Looper.myLooper() 得到当前线程的Looper就有可能为NULL。
判断Handler对象里面的Looper对象是属于哪条线程的,则由该线程来执行!
1. 当Handler对象的构造函数的参数为空,则为当前所在线程的Looper;
2. Looper.getMainLooper()得到的是主线程的Looper对象,Looper.myLooper()得到的是当前线程的Looper对象。
源码:
[java]  view plain copy
  1. public class MainActivity extends Activity implements OnClickListener {  
  2.     private Button startbutton = null;  
  3.     private TextView text = null;  
  4.     private MyHandler mHandler = null;  
  5.     private Thread thread;  
  6.   
  7.     @Override  
  8.     protected void onCreate(Bundle savedInstanceState) {  
  9.         super.onCreate(savedInstanceState);  
  10.         setContentView(R.layout.main);  
  11.         startbutton = (Button) findViewById(R.id.StartButton);  
  12.         startbutton.setOnClickListener(this);  
  13.         text = (TextView) findViewById(R.id.content);  
  14.     }  
  15.   
  16.     @Override  
  17.     public void onClick(View v) {  
  18.         switch (v.getId()) {  
  19.         case R.id.StartButton:  
  20.             // 每次单击都会建立一个新的线程,这肯定是不合适的  
  21.             thread = new MyThread();  
  22.             thread.start();// 开启一个子线程  
  23.             break;  
  24.         }  
  25.     }  
  26.   
  27.     private class MyHandler extends Handler {  
  28.         public MyHandler(Looper looper) {  
  29.             super(looper);  
  30.         }  
  31.   
  32.         @Override  
  33.         public void handleMessage(Message msg) { // 处理消息  
  34.             System.out  
  35.                     .println("handle--id-->" + Thread.currentThread().getId());// 1  
  36.             System.out.println("handle--name-->"  
  37.                     + Thread.currentThread().getName());// main  
  38.             text.setText(msg.obj.toString());// 此时handle在主线程当中,可以处理界面更新  
  39.         }  
  40.     }  
  41.     /** 
  42.      * Android 会自动替主线程建立Message Queue ,在这个子线程里并没有建立Message Queue 。 所以,myLooper 
  43.      * 值为null ,而mainLooper 则指向主线程里的Looper 。于是,执行到: mHandler = new MyHandler 
  44.      * (mainLooper); 此mHandler属于主线程。 mHandler.sendMessage(m); 
  45.      * @author andieguo 
  46.      */  
  47.     private class MyThread extends Thread {  
  48.         /** 
  49.          * Looper.myLooper();获得当前的Looper Looper.getMainLooper ();获得UI线程的Lopper 
  50.          */  
  51.         @Override  
  52.         public void run() {  
  53.             System.out.println("MyThread------id------>"  
  54.                     + Thread.currentThread().getId());  
  55.             System.out.println("MyThread------name------>"  
  56.                     + Thread.currentThread().getName());  
  57.             Looper curLooper = Looper.myLooper();// MyThread线程  
  58.             Looper mainLooper = Looper.getMainLooper();  
  59.             String msg;  
  60.             if (curLooper == null) {  
  61.                 // 把当前handler绑定在mainLooper线程上;此时mainLooper线程当中  
  62.                 mHandler = new MyHandler(mainLooper);  
  63.                 msg = "curLooper is null";  
  64.             } else {  
  65.                 mHandler = new MyHandler(curLooper);// 将mHandler与curLooper绑定  
  66.                 msg = "This is curLooper";  
  67.             }  
  68.             mHandler.removeMessages(0);  
  69.             Message m = mHandler.obtainMessage(111, msg);  
  70.             // mHandler对象而将消息m传给curLooper,然后放入MessageQueue里。  
  71.             // Looper对象看到MessageQueue里有消息m,就将它广播出去,mHandler对象接到此讯息时,会呼叫其handleMessage()函数来处理  
  72.             mHandler.sendMessage(m);// 将消息添加到了curLooper相关联的消息队列中;  
  73.         }  
  74.     }  
  75. }  
结果验证:
特别提醒:
源码链接:
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值