android消息分发机制之Java层Handler,Looper,Message及MessageQueue

先看android提供的一个关于Handler、Looper使用的最简单范例:

class LooperThread extends Thread {//线程类,在这个线程中会启用消息分发机制
      public Handler mHandler;
   //启动线程时会调用线程的run()方法
      public void run() {
          Looper.prepare(); //创建属于该线程的looper,looper中含messageQueue对象
      //创建handler用于发送消息,并传递Callback接口中handlerMessage方法的实现,Callback只有一个接口方法)
          mHandler = new Handler() {
              public void handleMessage(Message msg) {
                  // process incoming messages here
              }
          };
      //启动loop()死循环,读取消息(可能阻塞)-dispatch-读取消息
          Looper.loop();
      }
  }

第一部分:Looper.prepare()

每个线程只能有一个Looper对象,所以只能调用一次Looper.prepare。创建的Looper对象保存在线程间各自私有的本地存储区(TLS:Thread Local Stroage)。代码中体现在Looper有个sThreadLocal成员变量,创建后通过它获取该线程的looper对象。获取之前,必须先创建,创建调用Looper.prepare()静态方法,获取调用Looper.myLooper()静态方法。

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
 89     public static void prepare() {
 90         prepare(true);
 91     }
 92 
 93     private static void prepare(boolean quitAllowed) {
 94         if (sThreadLocal.get() != null) {//每个线程只允许执行一次该方法
 95             throw new RuntimeException("Only one Looper may be created per thread");
 96         }//创建Looper对象,并保存在TLS中
 97         sThreadLocal.set(new Looper(quitAllowed));
 98     }

看看Looper的构造函数

216     private Looper(boolean quitAllowed) {
217         mQueue = new MessageQueue(quitAllowed);//创建MessageQueue对象
218         mThread = Thread.currentThread();//调用Looper.prepare()的线程
219     }
 70     MessageQueue(boolean quitAllowed) {
 71         mQuitAllowed = quitAllowed;//是否允许调用MessageQueue.quit()方法
 72         mPtr = nativeInit();//jni调用到native层做啥?
 73     }
Looper.prepare():创建Looper对象并保存在ThreadLocalStorage区域,构造Looper时又创建了MessageQueue对象。


第二部分 启动死循环Looper.loop():读取消息-分发消息-读取消息

129     public static void loop() {
130         final Looper me = myLooper();//获取本线程的looper对象
131         if (me == null) {//调用Looper.loop()之前必须先调用Looper.prepare()方法
132             throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
133         }
134         final MessageQueue queue = me.mQueue;//Looper中的MessageQueue对象
135                                                                                                                                                                                      
136         // Make sure the identity of this thread is that of the local process,
137         // and keep track of what that identity token actually is.
138         Binder.clearCallingIdentity();
139         final long ident = Binder.clearCallingIdentity();
140 
141         for (;;) {//死循环
142             Message msg = queue.next(); //MessageQueue读取message, 可能阻塞?
143             if (msg == null) {
144                 // No message indicates that the message queue is quitting.
145                 return;
146             }
147 
148             // This must be in a local variable, in case a UI event sets the logger
149             final Printer logging = me.mLogging;
150             if (logging != null) {
151                 logging.println(">>>>> Dispatching to " + msg.target + " " +
152                         msg.callback + ": " + msg.what);
153             }
154 
155             final long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
156 
157             final long traceTag = me.mTraceTag;
158             if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
159                 Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
160             }
161             final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
162             final long end;
163             try {
164                 msg.target.dispatchMessage(msg);//获取message后,分发message给其target: Handler对象
165                 end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
166             } finally {
167                 if (traceTag != 0) {
168                     Trace.traceEnd(traceTag);
169                 }
170             }
171             if (slowDispatchThresholdMs > 0) {
172                 final long time = end - start;
173                 if (time > slowDispatchThresholdMs) {
174                     Slog.w(TAG, "Dispatch took " + time + "ms on "
175                             + Thread.currentThread().getName() + ", h=" +
176                             msg.target + " cb=" + msg.callback + " msg=" + msg.what);
177                 }
178             }
179 
180             if (logging != null) {
181                 logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
182             }
183 
184             // Make sure that during the course of dispatching the
185             // identity of the thread wasn't corrupted.
186             final long newIdent = Binder.clearCallingIdentity();
187             if (ident != newIdent) {
188                 Log.wtf(TAG, "Thread identity changed from 0x"
189                         + Long.toHexString(ident) + " to 0x"
190                         + Long.toHexString(newIdent) + " while dispatching to "
191                         + msg.target.getClass().getName() + " "
192                         + msg.callback + " what=" + msg.what);
193             }
194 
195             msg.recycleUnchecked();//msg重利用,重置并加入消息池,在需要消息时可以直接从消息池中获取,不用每次都new
196         }
197     }

分发消息:直接分发消息给target(Handler对象),target可能是一个继承自Handler并重写了handlerMessage()方法的子类,

也可能不继承Handler,构造Handler对象时传入Callback接口对象,Callback接口只有一个handlerMessage方法需实现。

target在dispather消息时优先级如下:msg.callback.run;Callback接口对象方法mCallback.handlerMessage;自身HandlerMessage()方法。

msg.target.dispatchMessage(msg)
 99     public void dispatchMessage(Message msg) {
100         if (msg.callback != null) {//第一优先级:msg.callback: Runnable对象
101             handleCallback(msg);//其实现为msg.callback.run()
102         } else {
103             if (mCallback != null) {
104                 if (mCallback.handleMessage(msg)) {//第二优先级,Callback mCallback,接口实现
105                     return;//无需继承Handler,构造Handler对象时传入Callback接口实现对象,Callback唯一接口方法handleMessage
106                 }
107             }
108             handleMessage(msg);//继承了Handler对象并重写handlerMessage
109         }
110     }

消息重利用:消息处理完之后,放入消息池,创建消息对象时推荐使用Message.obtain()方法,优先从消息池中获取,消息池没有在new一个message。

msg.recycleUnchecked()
293     void recycleUnchecked() {//回收消息
294         // Mark the message as in use while it remains in the recycled object pool.
295         // Clear out all other details.
296         flags = FLAG_IN_USE;//处于消息池中,需置in_use
297         what = 0;
298         arg1 = 0;
299         arg2 = 0;
300         obj = null;
301         replyTo = null; 
302         sendingUid = -1;
303         when = 0;
304         target = null;
305         callback = null;
306         data = null;
307             
308         synchronized (sPoolSync) {//加入消息池,栈方式
309             if (sPoolSize < MAX_POOL_SIZE) {
310                 next = sPool;//this.next---->sPool:
311                 sPool = this;
312                 sPoolSize++; 
313             }
314         }
315     }

获取消息

124     public static Message obtain() {
125         synchronized (sPoolSync) {
126             if (sPool != null) { //先看消息池中是否有消息
127                 Message m = sPool;//获取栈顶消息
128                 sPool = m.next;
129                 m.next = null;
130                 m.flags = 0; // clear in-use flag,出消息池,清除in_use flag
131                 sPoolSize--;
132                 return m;
133             }
134         }//消息池无消息,new一个
135         return new Message();
136     }

第三部分 Handler创建及发送消息

最开始的范例代码中,是直接new一个Handler对象,并只传入Callback对象,没有传入Looper对象(则使用当前线程的looper对象,即创建Handler之前需要调用Looper.prepare() )。

133     public Handler(Callback callback) {
134         this(callback, false);
135     }
194     public Handler(Callback callback, boolean async) {
195         if (FIND_POTENTIAL_LEAKS) {
196             final Class<? extends Handler> klass = getClass();
197             if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
198                     (klass.getModifiers() & Modifier.STATIC) == 0) {
199                 Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
200                     klass.getCanonicalName());
201             }
202         }
203 
204         //Handler中有个Looper成员变量
205         mLooper = Looper.myLooper();//获取当前线程的Looper
206         if (mLooper == null) {
207             throw new RuntimeException(
208                 "Can't create handler inside thread that has not called Looper.prepare()");
209         }
210         mQueue = mLooper.mQueue;//Looper中有个MessageQueue对象
211         //Callback接口类型,只有一个handMessage接口需要实现
212         //可以继承Handler,并实现其handMessage方法,或不继承,构造handler时传入一个Callback接口对象
213         mCallback = callback;
214         mAsynchronous = async;
215     }

Handler发送消息之前,会获取一个消息,方法如下:

290     public final Message obtainMessage()
291     {
292         return Message.obtain(this);//Message.target=this
293     }
301     public final Message obtainMessage(int what)
302     {
303         return Message.obtain(this, what);//message.what
304     }
315     public final Message obtainMessage(int what, Object obj)
316     {
317         return Message.obtain(this, what, obj);//message.obj
318     }
329     public final Message obtainMessage(int what, int arg1, int arg2)
330     {
331         return Message.obtain(this, what, arg1, arg2);//message.arg1, message.arg2
332     }
344     public final Message obtainMessage(int what, int arg1, int arg2, Object obj)
345     {
346         return Message.obtain(this, what, arg1, arg2, obj);
347     }

Handler.post(Runnable r)发送消息

sendMessage(msg):将消息插入触发时间小于等于current time + 0的所有pending消息之后

sendMessageDelayed(msg, delayMillos):将消息插入触发时间小于等于current time + delayMillis的所有pending消息之后
sendMessageAtTime(msg, updateMillos):将消息插入触发时间小于等于updateMillis的所有pending消息之后


Empty Message是值只指定what属性的消息

sendEmptyMessage(int what): ,消息触发时间是current time +0

sendMessageAtFrontOfQueue(msg): 插入消息到对头,消息触发时间是0,下一个loop循环就会被处理,可能引起时序问题

postXxxx(Runnable): 先获取消息getPostMessage(Runnable),再调用对应的sendMessageXxxx()方法


code:

360     public final boolean post(Runnable r)//设置消息的Runnable成员变量callback,dispath消息时第一优先级运行该Runnable对象
361     {                   
362        return  sendMessageDelayed(getPostMessage(r), 0);
363     }       
781     private static Message getPostMessage(Runnable r) {
782         Message m = Message.obtain();
783         m.callback = r;
784         return m;
785     }
786 
787     private static Message getPostMessage(Runnable r, Object token) {
788         Message m = Message.obtain();
789         m.obj = token;
790         m.callback = r;
791         return m;
792     }
383     public final boolean postAtTime(Runnable r, long uptimeMillis)
384     {//uptimeMillis:Runnable对象运行的绝对时间
385         return sendMessageAtTime(getPostMessage(r), uptimeMillis);
386     }
408     public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)
409     {//token: msg.obj
410         return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
411     }
432     public final boolean postDelayed(Runnable r, long delayMillis)
433     {//delayMillis:延时delayMillis时间后,Runnable对象才运行,如果还未触发该消息就Looper.quit(),则消息会丢掉,Runnable对象不被执行
434         return sendMessageDelayed(getPostMessage(r), delayMillis);
435     }
452     public final boolean postAtFrontOfQueue(Runnable r)
453     {
454         return sendMessageAtFrontOfQueue(getPostMessage(r));
455     }
541     public final boolean sendMessage(Message msg)
542     {
543         return sendMessageDelayed(msg, 0);
544     }
553     public final boolean sendEmptyMessage(int what)
554     {
555         return sendEmptyMessageDelayed(what, 0);
556     }
557 
558     /**
559      * Sends a Message containing only the what value, to be delivered
560      * after the specified amount of time elapses.
561      * @see #sendMessageDelayed(android.os.Message, long)-
562      *-
563      * @return Returns true if the message was successfully placed in to the-
564      *         message queue.  Returns false on failure, usually because the
565      *         looper processing the message queue is exiting.
566      */
567     public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
568         Message msg = Message.obtain();
569         msg.what = what;
570         return sendMessageDelayed(msg, delayMillis);
571     }
583     public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
584         Message msg = Message.obtain();
585         msg.what = what;
586         return sendMessageAtTime(msg, uptimeMillis);
587     }
601     public final boolean sendMessageDelayed(Message msg, long delayMillis)
602     {
603         if (delayMillis < 0) {
604             delayMillis = 0;
605         }
606         return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
607     }
628     public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
629         MessageQueue queue = mQueue;
630         if (queue == null) {
631             RuntimeException e = new RuntimeException(
632                     this + " sendMessageAtTime() called with no mQueue");
633             Log.w("Looper", e.getMessage(), e);
634             return false;
635         }
636         return enqueueMessage(queue, msg, uptimeMillis);
637     }
651     public final boolean sendMessageAtFrontOfQueue(Message msg) {
652         MessageQueue queue = mQueue;
653         if (queue == null) {
654             RuntimeException e = new RuntimeException(
655                 this + " sendMessageAtTime() called with no mQueue");
656             Log.w("Looper", e.getMessage(), e);
657             return false;
658         }
659         return enqueueMessage(queue, msg, 0);
660     }
662     private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
663         msg.target = this;
664         if (mAsynchronous) {//设置消息的同步属性,特定场景下,messageQueue中可能会引入同步屏障,在满足某个条件之前阻止同步消息的发送,异步消息发送不受影响。
665             msg.setAsynchronous(true);
666         }
667         return queue.enqueueMessage(msg, uptimeMillis);
668     }


剩余:MessageQueue native操作部分,MessageQueue.next() may block,MessageQueue.enqueueMessage

参考:Android消息机制1-Handler(Java层)




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值