推广网站的方法有搜索,制作小网站,海外网络推广服务,东游科技网站建设跟Handler有关系的#xff0c;包括Thread#xff0c;Looper#xff0c;Handler#xff0c;MessageQueue 
Looper: 
由于Looper是android包加入的类#xff0c;而Thread是java包的类#xff0c;所以#xff0c;想要为Thread创建一个Looper#xff0c;需要在线程内部调用…跟Handler有关系的包括ThreadLooperHandlerMessageQueue 
Looper: 
由于Looper是android包加入的类而Thread是java包的类所以想要为Thread创建一个Looper需要在线程内部调用Looper.prepare 
Looper内部会存储一个ThreadLocal因此每个线程都会有自己的一个Looper。 
Looper内部有自己存储了一个MessageQueue以及主线程的MainLooper。 调用Looper一般会有两个方法Looper.prepare以及Looper.loop方法 
Looper.prepare prepare会新创建一个Looper塞进ThreadLocal因此prepare必须在线程内部调用才能将线程本身作为key。 同时会创建MessageQueue以及存储当前线程。 
顺便看下两个比较常用的方法 
myLooper是从ThreadLocal中获取的当前线程所属的Looper。 
myQueue对应的是当前线程的Looper中存储的MessageQueue。 Looper.loop 
从Looper.loop方法可以看出几个细节 
通过调用MessageQueue.next获取下一个要处理的Message通过Message.target.dispatchMessage将Message提交给Message中存储的Handler去处理Handler调用dispatchMessage可以创建一个进程唯一的Observer去监听Message的分配以及处理结束的进度。 
public static void loop() {final Looper me  myLooper();if (me  null) {throw new RuntimeException(No Looper; Looper.prepare() wasnt called on this thread.);}if (me.mInLoop) {Slog.w(TAG, Loop again would have the queued messages be executed  before this one completed.);}me.mInLoop  true;final MessageQueue queue  me.mQueue;for (;;) {Message msg  queue.next(); // might blockif (msg  null) {// No message indicates that the message queue is quitting.return;}// This must be in a local variable, in case a UI event sets the loggerfinal Printer logging  me.mLogging;if (logging ! null) {logging.println( Dispatching to   msg.target    msg.callback  :   msg.what);}// Make sure the observer wont change while processing a transaction.final Observer observer  sObserver;final long traceTag  me.mTraceTag;long slowDispatchThresholdMs  me.mSlowDispatchThresholdMs;long slowDeliveryThresholdMs  me.mSlowDeliveryThresholdMs;if (thresholdOverride  0) {slowDispatchThresholdMs  thresholdOverride;slowDeliveryThresholdMs  thresholdOverride;}final boolean logSlowDelivery  (slowDeliveryThresholdMs  0)  (msg.when  0);final boolean logSlowDispatch  (slowDispatchThresholdMs  0);final boolean needStartTime  logSlowDelivery || logSlowDispatch;final boolean needEndTime  logSlowDispatch;if (traceTag ! 0  Trace.isTagEnabled(traceTag)) {Trace.traceBegin(traceTag, msg.target.getTraceName(msg));}final long dispatchStart  needStartTime ? SystemClock.uptimeMillis() : 0;final long dispatchEnd;Object token  null;if (observer ! null) {token  observer.messageDispatchStarting();}long origWorkSource  ThreadLocalWorkSource.setUid(msg.workSourceUid);try {msg.target.dispatchMessage(msg);if (observer ! null) {observer.messageDispatched(token, msg);}dispatchEnd  needEndTime ? SystemClock.uptimeMillis() : 0;} catch (Exception exception) {if (observer ! null) {observer.dispatchingThrewException(token, msg, exception);}throw exception;} finally {ThreadLocalWorkSource.restore(origWorkSource);if (traceTag ! 0) {Trace.traceEnd(traceTag);}}if (logSlowDelivery) {if (slowDeliveryDetected) {if ((dispatchStart - msg.when)  10) {Slog.w(TAG, Drained);slowDeliveryDetected  false;}} else {if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, delivery,msg)) {// Once we write a slow delivery log, suppress until the queue drains.slowDeliveryDetected  true;}}}if (logSlowDispatch) {showSlowLog(slowDispatchThresholdMs, dispatchStart, dispatchEnd, dispatch, msg);}if (logging ! null) {logging.println( Finished to   msg.target     msg.callback);}// Make sure that during the course of dispatching the// identity of the thread wasnt corrupted.final long newIdent  Binder.clearCallingIdentity();if (ident ! newIdent) {Log.wtf(TAG, Thread identity changed from 0x Long.toHexString(ident)   to 0x Long.toHexString(newIdent)   while dispatching to  msg.target.getClass().getName()    msg.callback   what  msg.what);}msg.recycleUnchecked();}
} 
Message 
从Looper.loop方法可以看出会对Looper的MessageQueue遍历不断取出Message然后调用Message.target.dispatchMessage方法。 
从Message的变量可以看出target实际是Message所属的Handler。 
同时Message存储了一个next说明MessageQueue是一个链式结构。 MessageQueue 
https://www.cnblogs.com/jiy-for-you/p/11707356.html 
从MessageQueue.next可以获取几个有效信息 
nativePollOnceMessageQueue中没有Message的时候会卡在这个方法类似于object.wait当有人调用MessageQueue.enqueueMessage方法的时候会将线程唤醒。msg.target  null代表该msg是一个同步屏障即阻拦同步消息的执行。遇到同步屏障时会往后遍历优先执行异步消息触发view的绘制的那个消息就是异步消息。如果获取到一个msgmsg.when代表的执行时间还没到会先去执行IdleHandler里面的消息或MessageQueue队列为空。 // MessageQueue.next
Message next() {// Return here if the message loop has already quit and been disposed.// This can happen if the application tries to restart a looper after quit// which is not supported.final long ptr  mPtr;if (ptr  0) {return null;}int pendingIdleHandlerCount  -1; // -1 only during first iterationint nextPollTimeoutMillis  0;for (;;) {if (nextPollTimeoutMillis ! 0) {Binder.flushPendingCommands();}// 如果没有消息会卡在这个方法nativePollOnce(ptr, nextPollTimeoutMillis);synchronized (this) {// Try to retrieve the next message.  Return if found.final long now  SystemClock.uptimeMillis();Message prevMsg  null;Message msg  mMessages;if (msg ! null  msg.target  null) {// 同步屏障当遇到同步屏障,会往后寻找异步消息isAsynchronous执行// Stalled by a barrier.  Find the next asynchronous message in the queue.do {// 遍历直到找到一个异步的msgprevMsg  msg;// 这一步prevMsg!null这会导致msg  msg.next;} while (msg ! null  !msg.isAsynchronous());}if (msg ! null) {if (now  msg.when) {// msg.when是这个message的执行时间如果message的执行时间在now之后// Next message is not ready.  Set a timeout to wake up when it is ready.nextPollTimeoutMillis  (int) Math.min(msg.when - now, Integer.MAX_VALUE);} else {// Got a message.mBlocked  false;if (prevMsg ! null) {prevMsg.next  msg.next;} else {mMessages  msg.next;}msg.next  null;if (DEBUG) Log.v(TAG, Returning message:   msg);msg.markInUse();return msg;}} else {// No more messages.nextPollTimeoutMillis  -1;}// Process the quit message now that all pending messages have been handled.if (mQuitting) {dispose();return null;}// If first time idle, then get the number of idlers to run.// Idle handles only run if the queue is empty or if the first message// in the queue (possibly a barrier) is due to be handled in the future.// 走到这说明消息队列是空的或队首是一个延迟执行的Messageif (pendingIdleHandlerCount  0 (mMessages  null || now  mMessages.when)) {pendingIdleHandlerCount  mIdleHandlers.size();}if (pendingIdleHandlerCount  0) {// No idle handlers to run.  Loop and wait some more.mBlocked  true;continue;}if (mPendingIdleHandlers  null) {mPendingIdleHandlers  new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];}mPendingIdleHandlers  mIdleHandlers.toArray(mPendingIdleHandlers);}// Run the idle handlers.// We only ever reach this code block during the first iteration.for (int i  0; i  pendingIdleHandlerCount; i) {final IdleHandler idler  mPendingIdleHandlers[i];mPendingIdleHandlers[i]  null; // release the reference to the handlerboolean keep  false;try {keep  idler.queueIdle();} catch (Throwable t) {Log.wtf(TAG, IdleHandler threw exception, t);}if (!keep) {synchronized (this) {mIdleHandlers.remove(idler);}}}// Reset the idle handler count to 0 so we do not run them again.pendingIdleHandlerCount  0;// While calling an idle handler, a new message could have been delivered// so go back and look again for a pending message without waiting.nextPollTimeoutMillis  0;}
}Handler的总结 
Handler内部一定会有一个Looper。Looper跟线程一一绑定。绑定的关系存在Looper的sThreadLocal中。所以如果Handler想要监听哪个线程上的消息可以直接给Handler传那个线程的Looper即可。Looper实际上是一个轮询消息的机制所以内部一定会存在一个MessageQueue。当Looper开始轮询的时候调用Looper.loop会每次调用MessageQueue.next取一个Message出来执行。Looper获取到Message之后会调用Message.target.dispatchMessage方法。即实际调用的是Handler.dispatchMessage的方法。Message中有几个比较重要的参数 target这个Message从属于哪个handler从哪个handler post过去的。callback当调用handler.postRunnable即创建了一个Messagemsg.callBack  runnable。what这个Message的唯一标识id。当Handler.handleMessage方法中会接收多个message通过what区分这个Message的类别。when通过handler.postDelayed设置这个Message实际应该执行的时间curTimedelay。MessageQueue的入队实际是通过when去进行Message的排序的。handler.dispatchMessage方法 如果Message.callback ! null直接执行Message.callback.run即post(Runnable)中Runnable的执行。否则如果给handler设置了Callback就调用Callback.handleMessage否则调用Handler本身的handleMessage方法空实现需要重写。 
关于barrier 
// MessageQueue
private int postSyncBarrier(long when) {// Enqueue a new sync barrier token.// We dont need to wake the queue because the purpose of a barrier is to stall it.synchronized (this) {final int token  mNextBarrierToken;final Message msg  Message.obtain();msg.markInUse();msg.when  when;msg.arg1  token;// 代表Message的barrier特征是target  nullMessage prev  null;Message p  mMessages;if (when ! 0) {// 根据when将代表barrier的msg插入MessageQueuewhile (p ! null  p.when  when) {prev  p;p  p.next;}}if (prev ! null) { // invariant: p  prev.nextmsg.next  p;prev.next  msg;} else {msg.next  p;mMessages  msg;}return token;}
} 
postSyncBarrier生成一个target  null的Message根据when插入MessageQueue中。返回的token是barrier的唯一标识。只要postSyncBarrier就要根据这个token后面移除barrier。否则会导致同步消息一直无法执行。 
看下有了barrier的MessageQueue取Message的时候是怎么表现的。 
Message next() {// Return here if the message loop has already quit and been disposed.// This can happen if the application tries to restart a looper after quit// which is not supported.final long ptr  mPtr;if (ptr  0) {return null;}int pendingIdleHandlerCount  -1; // -1 only during first iterationint nextPollTimeoutMillis  0;for (;;) {if (nextPollTimeoutMillis ! 0) {Binder.flushPendingCommands();}nativePollOnce(ptr, nextPollTimeoutMillis);// nextPollTimeoutMillis:等待的时间synchronized (this) {// Try to retrieve the next message.  Return if found.final long now  SystemClock.uptimeMillis();Message prevMsg  null;Message msg  mMessages;if (msg ! null  msg.target  null) {// 如果取msg的时候队首的Msg是Barrier// Stalled by a barrier.  Find the next asynchronous message in the queue.do {prevMsg  msg;msg  msg.next;// 就一直往后遍历寻找一个异步的msg} while (msg ! null  !msg.isAsynchronous());}if (msg ! null) {if (now  msg.when) {// 如果还没到msg的执行时间就设置nextPollTimeoutMillis// Next message is not ready.  Set a timeout to wake up when it is ready.nextPollTimeoutMillis  (int) Math.min(msg.when - now, Integer.MAX_VALUE);} else {// Got a message.mBlocked  false;if (prevMsg ! null) {prevMsg.next  msg.next;} else {mMessages  msg.next;}msg.next  null;if (DEBUG) Log.v(TAG, Returning message:   msg);msg.markInUse();return msg;}} else {// 如果mMessages队列为空或有Barrier的时候异步msg为空就设置等待时间为-1// 为-1代表等待被唤醒// No more messages.nextPollTimeoutMillis  -1;}// Process the quit message now that all pending messages have been handled.if (mQuitting) {dispose();return null;}// If first time idle, then get the number of idlers to run.// Idle handles only run if the queue is empty or if the first message// in the queue (possibly a barrier) is due to be handled in the future.if (pendingIdleHandlerCount  0 (mMessages  null || now  mMessages.when)) {pendingIdleHandlerCount  mIdleHandlers.size();}// 如果队列为空或者还没到message的执行时间开始执行IdleHandlerif (pendingIdleHandlerCount  0) {// No idle handlers to run.  Loop and wait some more.mBlocked  true;continue;}if (mPendingIdleHandlers  null) {mPendingIdleHandlers  new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];}mPendingIdleHandlers  mIdleHandlers.toArray(mPendingIdleHandlers);}// Run the idle handlers.// We only ever reach this code block during the first iteration.for (int i  0; i  pendingIdleHandlerCount; i) {final IdleHandler idler  mPendingIdleHandlers[i];mPendingIdleHandlers[i]  null; // release the reference to the handlerboolean keep  false;try {keep  idler.queueIdle();} catch (Throwable t) {Log.wtf(TAG, IdleHandler threw exception, t);}if (!keep) {synchronized (this) {mIdleHandlers.remove(idler);}}}// Reset the idle handler count to 0 so we do not run them again.// 防止下次再走一遍IdleHandlerpendingIdleHandlerCount  0;// While calling an idle handler, a new message could have been delivered// so go back and look again for a pending message without waiting.// 经过IdleHandler之后可能已经有Message入队了再遍历一遍第二次就直接等待了。nextPollTimeoutMillis  0;}
} 
总结下next的逻辑 
如果mMessages的队首是barrier(msg.target  null)就遍历messages优先执行异步消息异步消息一般是优先级最高的信息比如响应input事件或是view刷新。。如果不是barrier就直接取队首的message执行。如果12步骤取到的message ! null先看message的when  now大于则直接返回message给Looper.loop方法。小于则设置nextPollTimeoutMillis用来设置线程的等待时间nativePollOnce。如果messageQueue为空或message.when  now(即要等待)那么这个时候就去执行IdleHandler。 
总结下上面nativePollOnce其实代表线程在等待下一个消息的执行或者messages队列为空。或者是设置了barrier情况下没有异步消息的时候。 
下一步看下MessageQueue的具体打出日志代表什么。 文章转载自: http://www.morning.kghss.cn.gov.cn.kghss.cn http://www.morning.mtgnd.cn.gov.cn.mtgnd.cn http://www.morning.kkgbs.cn.gov.cn.kkgbs.cn http://www.morning.lsjtq.cn.gov.cn.lsjtq.cn http://www.morning.qzpkr.cn.gov.cn.qzpkr.cn http://www.morning.tcsdlbt.cn.gov.cn.tcsdlbt.cn http://www.morning.rlns.cn.gov.cn.rlns.cn http://www.morning.sqgqh.cn.gov.cn.sqgqh.cn http://www.morning.hncrc.cn.gov.cn.hncrc.cn http://www.morning.znnsk.cn.gov.cn.znnsk.cn http://www.morning.xyrw.cn.gov.cn.xyrw.cn http://www.morning.lfxcj.cn.gov.cn.lfxcj.cn http://www.morning.gthwz.cn.gov.cn.gthwz.cn http://www.morning.qgzmz.cn.gov.cn.qgzmz.cn http://www.morning.yjknk.cn.gov.cn.yjknk.cn http://www.morning.sqgqh.cn.gov.cn.sqgqh.cn http://www.morning.cxsdl.cn.gov.cn.cxsdl.cn http://www.morning.ygwyt.cn.gov.cn.ygwyt.cn http://www.morning.lfqnk.cn.gov.cn.lfqnk.cn http://www.morning.bmzxp.cn.gov.cn.bmzxp.cn http://www.morning.pbsqr.cn.gov.cn.pbsqr.cn http://www.morning.qydgk.cn.gov.cn.qydgk.cn http://www.morning.trnl.cn.gov.cn.trnl.cn http://www.morning.kydrb.cn.gov.cn.kydrb.cn http://www.morning.ggtkk.cn.gov.cn.ggtkk.cn http://www.morning.rnht.cn.gov.cn.rnht.cn http://www.morning.wfzlt.cn.gov.cn.wfzlt.cn http://www.morning.ptmsk.cn.gov.cn.ptmsk.cn http://www.morning.dfltx.cn.gov.cn.dfltx.cn http://www.morning.tslxr.cn.gov.cn.tslxr.cn http://www.morning.btcgq.cn.gov.cn.btcgq.cn http://www.morning.pgxjl.cn.gov.cn.pgxjl.cn http://www.morning.yxplz.cn.gov.cn.yxplz.cn http://www.morning.bhxzx.cn.gov.cn.bhxzx.cn http://www.morning.bxrqf.cn.gov.cn.bxrqf.cn http://www.morning.rxnl.cn.gov.cn.rxnl.cn http://www.morning.qbjgw.cn.gov.cn.qbjgw.cn http://www.morning.fmkjx.cn.gov.cn.fmkjx.cn http://www.morning.jlboyuan.cn.gov.cn.jlboyuan.cn http://www.morning.dmlgq.cn.gov.cn.dmlgq.cn http://www.morning.zbhfs.cn.gov.cn.zbhfs.cn http://www.morning.xknmn.cn.gov.cn.xknmn.cn http://www.morning.mmclj.cn.gov.cn.mmclj.cn http://www.morning.zlxrg.cn.gov.cn.zlxrg.cn http://www.morning.zfyr.cn.gov.cn.zfyr.cn http://www.morning.wjtxt.cn.gov.cn.wjtxt.cn http://www.morning.nbsfb.cn.gov.cn.nbsfb.cn http://www.morning.wncb.cn.gov.cn.wncb.cn http://www.morning.lxqkt.cn.gov.cn.lxqkt.cn http://www.morning.thpzn.cn.gov.cn.thpzn.cn http://www.morning.mjats.com.gov.cn.mjats.com http://www.morning.qpfmh.cn.gov.cn.qpfmh.cn http://www.morning.kydrb.cn.gov.cn.kydrb.cn http://www.morning.bauul.com.gov.cn.bauul.com http://www.morning.nyjgm.cn.gov.cn.nyjgm.cn http://www.morning.qichetc.com.gov.cn.qichetc.com http://www.morning.wrtpk.cn.gov.cn.wrtpk.cn http://www.morning.grbp.cn.gov.cn.grbp.cn http://www.morning.qydgk.cn.gov.cn.qydgk.cn http://www.morning.swsrb.cn.gov.cn.swsrb.cn http://www.morning.bmts.cn.gov.cn.bmts.cn http://www.morning.shinezoneserver.com.gov.cn.shinezoneserver.com http://www.morning.wwxg.cn.gov.cn.wwxg.cn http://www.morning.ntffl.cn.gov.cn.ntffl.cn http://www.morning.lslin.com.gov.cn.lslin.com http://www.morning.zgnng.cn.gov.cn.zgnng.cn http://www.morning.wmhqd.cn.gov.cn.wmhqd.cn http://www.morning.pznqt.cn.gov.cn.pznqt.cn http://www.morning.vibwp.cn.gov.cn.vibwp.cn http://www.morning.dpplr.cn.gov.cn.dpplr.cn http://www.morning.tmsxn.cn.gov.cn.tmsxn.cn http://www.morning.xrnh.cn.gov.cn.xrnh.cn http://www.morning.bkqw.cn.gov.cn.bkqw.cn http://www.morning.rfwkn.cn.gov.cn.rfwkn.cn http://www.morning.tsdjj.cn.gov.cn.tsdjj.cn http://www.morning.gtmgl.cn.gov.cn.gtmgl.cn http://www.morning.hhxkl.cn.gov.cn.hhxkl.cn http://www.morning.fdfdz.cn.gov.cn.fdfdz.cn http://www.morning.rnpt.cn.gov.cn.rnpt.cn http://www.morning.gtdf.cn.gov.cn.gtdf.cn