Handler消息传递机制(二)Handler,Loop,Message,MessageQueue的工作原理

19 篇文章 0 订阅


http://blog.csdn.net/tuke_tuke/article/details/50783153

Loop,Message,MessageQueue概念理解:

Message:Handler发送、接收和处理的消息对象

Looper:每个线程只能拥有一个Looper.它的looper()方法负责循环读取MessageQueue中的消息并将读取到的消息交给发送该消息的handler进行处理。

MessageQueue:消息队列,它采用先进先出的方式来管理Message。程序在创建Looper对象时,会在它的构造器中创建MessageQueue

Looper提供的源码如下:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. private Looper(boolean quitAllowed) {  
  2.         mQueue = new MessageQueue(quitAllowed);  
  3.          mThread = Thread.currentThread();  
  4.      }  

从源码第2行中可以看出,在创建Looper对象时会创建一个与之关联的MessageQueue对象。构造器是private修饰的,所以程序员是无法创建Looper对象的,就是说创建Looper同时就创建了MessageQueue对象

Handler:前面说Handler作用有两个---发送消息和处理消息,Handler发送的消息必须被送到指定的MessageQueue,也就是说,要想Handler正常工作必须在当前线程中有一个MessageQueue,否则消息没法保存。而MessageQueue是由Looper负责管理的,因此要想Handler正常工作,必须在当前线程中有一个Looper对象,这里分为两种情况:

1>主线程(UI线程),系统已经初始化了一个Looper对象,因此程序直接创建Handler即可
2>程序员自己创建的子线程,这时,程序员必须创建一个Looper对象,并启动它。


创建Looper:使用Looper.prepare(),查看源码

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public static void prepare() {  
  2.         prepare(true);  
  3.      }  
  4.     
  5.    private static void prepare(boolean quitAllowed) {  
  6.           if (sThreadLocal.get() != null) {  
  7.              throw new RuntimeException("Only one Looper may be created per thread");  
  8.           }  
  9.           sThreadLocal.set(new Looper(quitAllowed));  
  10.     }  
  11.    
  12.    private Looper(boolean quitAllowed) {  
  13.          mQueue = new MessageQueue(quitAllowed);  
  14.          mThread = Thread.currentThread();  
  15.      }  

通过方法调用,第9行创建Looper对象,创建Looper对象时同时会创建MessageQueue对象(第13行)。此外,可以看出prepare()允许一个线程最多有一个Looper被创建


启动Looper:Looper.loop(),loop()使用一个死循环不断取出MessageQueue中的消息,并将消息发送给对应的Handler进行处理。下面是Looper类中looper()方法的部分源码

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. for (;;) {  
  2.               Message msg = queue.next(); // might block  
  3.               if (msg == null) {  
  4.                 // No message indicates that the message queue is quitting.  
  5.                   return;  
  6.               }  
  7.     
  8.               // This must be in a local variable, in case a UI event sets the logger  
  9.               Printer logging = me.mLogging;  
  10.              if (logging != null) {  
  11.                  logging.println(">>>>> Dispatching to " + msg.target + " " +  
  12.                          msg.callback + ": " + msg.what);  
  13.             }  
  14.   
  15.             msg.target.dispatchMessage(msg);  
  16.   
  17.              if (logging != null) {  
  18.                  logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);  
  19.             }  
  20.    
  21.              // Make sure that during the course of dispatching the  
  22.              // identity of the thread wasn't corrupted.  
  23.              final long newIdent = Binder.clearCallingIdentity();  
  24.              if (ident != newIdent) {  
  25.                  Log.wtf(TAG, "Thread identity changed from 0x"  
  26.                          + Long.toHexString(ident) + " to 0x"  
  27.                          + Long.toHexString(newIdent) + " while dispatching to "  
  28.                          + msg.target.getClass().getName() + " "  
  29.                         + msg.callback + " what=" + msg.what);  
  30.              }  
  31.    
  32.              msg.recycleUnchecked();  
  33.         }  
很明显第1行用了一个死循环,第2行从queue中取出Message,第15行通过dispatchMessage(Message msg)方法将消息发送给Handler。

Looper,MessageQueue,Handler的各自作用如下:

Looper:每个线程只有一个Looper,他负责管理MessageQueue,会不断的从MessageQueue中取出消息,将消息交给对应的Handler处理

MessageQueue:由Looper负责管理,是用来存放线程放入的消息。

Handler:它把消息发送给Looper管理的MessageQueue,并负责处理Looper分给它的消息

在线程中Handler的使用步骤是

(1)调用 Looper的prepare()方法为当前线程创建Looper对象,创建Looper对象时,它的构造器会创建与之配套的MessageQueue。
(2)有了Looper之后,创建Handler子类的实例,重写HandlerMessage()方法,该方法负责处理来自其它线程的消息。
(3)调用Looper的loop()方法启动Looper。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值