Message, MessageQueue, Handler, Looper内部构造

一、Message

1.Field
     public int what;               //message code
     public int arg1;
     public int arg2;     
     public Object obj;            

     long when;                     //消息何时执行,是否延迟
     Handler target;                //
      Runnable callback;        // 
      Message next;               //消息链,单向链表结构     

     private static final Object sPoolSync = new Object();
      private static Message sPool;       //缓存池,采用了单向链表的方式
     private static int sPoolSize;          //池中消息的数量

2.Method

     public static Message obtain() {
          synchronized(sPoolSync) {
               if(sPool != null) {
                    Message m = sPool;               //从消息池中取出一个已用过的消息对象,达到对象复用
                    sPool = m.next;                      //注意这里取出的是链表头
                    m.next = null;
                    sPoolSize--;
                    return m;
               }
          }
          return new Message();
     }

     public void recycle() {
          clearForRecycle();
          synchronized(sPoolSync) {
               if(sPoolSize < MAX_POOL_SIZE) {
                    next = sPool;           //每次Message被用过后,都将已用过的消息放到链表头里面,
                    sPool = this;            //如果缓存池数量已达最大限制,则不缓存
                    sPoolSize++;
               }
          }
     }

      Message里有一个缓存池,采用了一个单向链表来存储所有已经用过的消息,每次构造Message对象时,最优的方式是直接调用obtain()方法来获取缓存对象。


二、MessageQueue     
    1.Field:
          Message  mMessages;
          顾名思义,第一感觉内部应该有个队列queue,比方说用List、Array、Map等来存储,但这里只有一个Message对象,那它使怎么存储这个队列的呢?
          由前面可以看到,Message其实在内部定义了个单向的链表结构,所以在MessageQueue里只需要记住这个链表的表头就可以了。     

     2.Method:
          final Message next()
     
          final void quit();

          final boolean enqueueMessage(Message msg, long when) {
               ……
               …...
               Message p = mMessage;          //获取链表头的message消息对象
                //如果消息池里消息为空,或者该消息响应的时间已过,或者链表头的消息大于该消息的时间
               //则将该消息放在表头,相当于会立马执行
               if(p == null || when == 0 || when < p.when) {
                    msg.next = p;         
                    mMessage = msg;
                    …...
               } else {
                    ……
                    Message prev;
                    for( ; ; ) {           //遍历单向链表
                         prev = p;
                         p = p.next;
                         if(p == null || when < p.when) {
                              break;
                         }
                         …...
                    }
                    msg.next = p;
                    prev.next = msg;      //根据Message要执行的时间,按从小到大进行排序,把该消息插入到
                                                  //链表当中对应的位置
               }
               ……
               …...
          }
           MessageQueue中将message加入队列的过程,实际上是在操作message的单向链表,按message的执行时间进行排序的过程。
                     

三、Handler
     1.Field
          final MessageQueue mQueue;
          final Looper mLooper;
          final Callback mCallback;
     一个Handler里面包括1个MessageQueue,1个Looper,1个Callback。
     可以允许多个Handler对象共用一个Looper对象,也即共用同一个MessageQueue。

     2.Method

          public void handleMessage(Message msg) {
          }
          
          //在这里进行消息的分发
          public void dispatchMessage(Message msg) {
               if(msg.callback != null) {          // 如果Message的Callback不为空的话,会执行其Callback方法
                    handleCallback(msg);         //这个时候,并不会执行Handler的handlerMessage()方法
               } else {     //
                    if(mCallback != null) {           //如果Handler的Callback不为空的话,会先执行其Callback
                         if(mCallback.handleMessage(msg)) {
                              return;
                         }
                    }
                    handleMessage(msg);
               }
          }
          所以,Handler在进行消息分发时,会有个先后顺序:1.优先执行Message的Callback,实际上是个Runnable对象;2.如果Message的Callback为空,则优先执行Handler的Callback;3.如果Message、Handler的Callback都为空,最后才会执行handleMessage()方法;4.如果Handler的Callback不为空,并且return true,则不会执行handleMessage()方法,如果return false,则Handler的Callback与handleMessage()均会执行。
          可以看到,handleMessage()方法并不一定会执行,它执行的优先级最低。

          //实际上是构造了一个Message对象,该Message的Callback为该Runnable
          public final boolean post(Runnable r) {
               return sendMessageDelayed(getPostMessage(r), 0);     
          }

          private static Message getPostMessage(Runnable r) {
               Message m = Message.obtain();
               m.callback = r;
               return m;
          }


四、Looper
     1.Field
     
     //其实是采用ThreadLocal来存储与每个线程相关的Looper对象
     static final ThreadLocal<Looper> sTreadLocal = new TreadLocal<Looper>();

     final MessageQueue mQueue;          //每个Looper都有一个MessageQueue
     final Thread mThread;                      //与该Looper相关联的线程对象
     volatile boolean mRun;                     
     
     可见,每个Looper对象,都会创建一个MessageQueue对象,并且都会有一个与之相关联的Thread。

     2.Method
     
     //创建一个Looper对象,并将Looper对象存储在ThreadLocal当中,在这里建立了Looper对象与Thread之间的关联
     private static void prepare(boolean quitAllowed) {
          if(sThreadLocal.get() != null) {
               throw new RuntimeException("Only one Looper may be created per thread");
          }
          sThreadLocal.set(new Looper(quitAllowed));
     }

     //获取与该线程相关的Looper对象
     public static Looper myLooper() {
          return sThreadLocal.get();
     }

     //退出Looper循环
     public void quit() {
          mQueue.quit();
     }

     //在这里进入消息循环,不停的从消息池里取出消息进行处理。如果消息池里没有消息,则等待,如果有新的消息进来,则被唤醒。
      //这里是个死循环,当该Looper对象不需要用到的时候,要确保调用quit()方法,退出消息循环,释放资源。
     public static void loop() {
          ……
          …...
          for( ; ; ) {
               Message msg = queue.next();     //might block
               if(msg == null) {
                    return;
               }
               ……
               //这里会调用Handler的dispatchMessage()方法
               msg.target.dispatchMessage(msg);     
               ……
               //消息处理完毕后,会将该消息对象放入缓存池中
               msg.recycle();
          }
          …...
     }     


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值