面试被拒了两次表示很伤心。。。自己基础都忘光了

第一次遇到的一面试官大大还是很好的,他和我说即使搬砖也要搬地比别人好,推荐我多看看博客,自己平常时间多研究研究新技术。

工作三年,不常用的基础知识几乎忘光了,从基础开始吧。

-------------------------------------------------开始啦------------------------------------------------

前言:前段时间面试被问到handler的一些知识,面试官让我说说对handler的认识,我只记得handler、looper、message等零碎知识,系统的确实不大记得住了,现在回顾一下,并结合源码加深一下理解。

先搜搜大咖的对handler写的博客有个初步的认识。。。

1.handler基础

转载自http://blog.csdn.net/u012827296/article/details/51236614

点击打开链接

特别喜欢下面的图,配合再下面的文字讲的特别清楚。

Handler的消息处理主要有五个部分组成,Message,Handler,Message Queue,Looper和ThreadLocal。首先简要的了解这些对象的概念

Message:Message是在线程之间传递的消息,它可以在内部携带少量的数据,用于线程之间交换数据。Message有四个常用的字段,what字段,arg1字段,arg2字段,obj字段。what,arg1,arg2可以携带整型数据,obj可以携带object对象。

Handler:它主要用于发送和处理消息的发送消息一般使用sendMessage()方法,还有其他的一系列sendXXX的方法,但最终都是调用了sendMessageAtTime方法,除了sendMessageAtFrontOfQueue()这个方法

而发出的消息经过一系列的辗转处理后,最终会传递到Handler的handleMessage方法中。

Message Queue:MessageQueue是消息队列的意思,它主要用于存放所有通过Handler发送的消息,这部分的消息会一直存在于消息队列中,等待被处理。每个线程中只会有一个MessageQueue对象。

Looper:每个线程通过Handler发送的消息都保存在,MessageQueue中,Looper通过调用loop()的方法,就会进入到一个无限循环当中,然后每当发现Message Queue中存在一条消息,就会将它取出,并传递到Handler的handleMessage()方法中。每个线程中只会有一个Looper对象。(补充一下,子线程调用handler要先调用Looper.prepare()

ThreadLocal:MessageQueue对象,和Looper对象在每个线程中都只会有一个对象,怎么能保证它只有一个对象,就通过ThreadLocal来保存。Thread Local是一个线程内部的数据存储类,通过它可以在指定线程中存储数据,数据存储以后,只有在指定线程中可以获取到存储到数据,对于其他线程来说则无法获取到数据。(这个不是很明白)

2.源码分析(Android O)

上面转载的博客不知道是基于Android哪个版本写的,既然现在版本都到Android O了,与时俱进一下,基于Android O来分析一下=-=

Handler的源码路径在:./frameworks/base/core/java/android/os/Handler.java

我的源码是从清华大学的镜像库下载的:https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/

framework所在分支默认为:aosp/master

上面的oreo肯定是O的源码,至于aosp/master就不知道是啥了=-=但是既然下载的是最新的,姑且认为是Android O的吧。后续有确切答案更新。

版本号命名信息:

细分版本    分支    版本    支持的设备
OPR5.170623.007    android-8.0.0_r17    Oreo    Nexus 6P
OPR4.170623.009    android-8.0.0_r16    Oreo    Nexus 5X
OPR3.170623.008    android-8.0.0_r15    Oreo    Pixel XL、Pixel
OPR1.170623.027    android-8.0.0_r13    Oreo    Pixel XL、Pixel、Pixel C
OPR6.170623.021    android-8.0.0_r12    Oreo    Nexus Player
OPR6.170623.019    android-8.0.0_r11    Oreo    Nexus 6P
OPR4.170623.006    android-8.0.0_r10    Oreo    Nexus 5X
OPR3.170623.007    android-8.0.0_r9    Oreo    Pixel XL、Pixel
OPR1.170623.026    android-8.0.0_r7    Oreo    Pixel XL、Pixel、Pixel C
OPR6.170623.013    android-8.0.0_r4    Oreo    Nexus 5X、Nexus 6P
OPR6.170623.012    android-8.0.0_r3    Oreo    Pixel XL、Pixel
OPR6.170623.011    android-8.0.0_r2    Oreo    Pixel XL、Pixel

OPR6.170623.010    android-8.0.0_r1    Oreo    Pixel C

PS:

从 Oreo 开始,每个细分版本均采用新的细分版本号格式,即 PVBB.YYMMDD.bbb。

P 部分表示平台版本代号的第一个字母,例如 O 表示 Oreo。

V 部分表示支持的行业。按照惯例,P 表示主要平台分支。

BB 部分表示由字母和数字组成的代码,Google 可通过该代码识别相应细分版本所属的确切代码分支。

YYMMDD 部分表示相应版本从开发分支细分出来或与开发分支同步的日期。它并不一定是细分版本的确切构建日期,Google 常常会在现有细分版本中增加细微的更改,并在新细分版本中重复使用与现有细分版本相同的日期代码。

bbb 部分表示具有相同日期代码的不同版本,从 001 开始。

2.1 API注释

/**
 * A Handler allows you to send and process {@link Message} and Runnable
 * objects associated with a thread's {@link MessageQueue}.  Each Handler
 * instance is associated with a single thread and that thread's message
 * queue.  When you create a new Handler, it is bound to the thread /
 * message queue of the thread that is creating it -- from that point on,
 * it will deliver messages and runnables to that message queue and execute
 * them as they come out of the message queue.
 *
 * <p>There are two main uses for a Handler: (1) to schedule messages and
 * runnables to be executed as some point in the future; and (2) to enqueue
 * an action to be performed on a different thread than your own.
 *
 * <p>Scheduling messages is accomplished with the
 * {@link #post}, {@link #postAtTime(Runnable, long)},
 * {@link #postDelayed}, {@link #sendEmptyMessage},
 * {@link #sendMessage}, {@link #sendMessageAtTime}, and
 * {@link #sendMessageDelayed} methods.  The <em>post</em> versions allow
 * you to enqueue Runnable objects to be called by the message queue when
 * they are received; the <em>sendMessage</em> versions allow you to enqueue
 * a {@link Message} object containing a bundle of data that will be
 * processed by the Handler's {@link #handleMessage} method (requiring that
 * you implement a subclass of Handler).
 *
 * <p>When posting or sending to a Handler, you can either
 * allow the item to be processed as soon as the message queue is ready
 * to do so, or specify a delay before it gets processed or absolute time for
 * it to be processed.  The latter two allow you to implement timeouts,
 * ticks, and other timing-based behavior.
 *
 * <p>When a
 * process is created for your application, its main thread is dedicated to
 * running a message queue that takes care of managing the top-level
 * application objects (activities, broadcast receivers, etc) and any windows
 * they create.  You can create your own threads, and communicate back with
 * the main application thread through a Handler.  This is done by calling
 * the same <em>post</em> or <em>sendMessage</em> methods as before, but from
 * your new thread.  The given Runnable or Message will then be scheduled
 * in the Handler's message queue and processed when appropriate.
 */

简单地理解一下API

1)handler自从创建初始就和创建它的线程进行绑定。

2)handler有两个作用:定时调用和跨进程调用

api最后主要讲了一个Android的常用场景:当UI线程(主线程)有耗时操作的时候可以另起一个线程用于处理,调用handler进行新线程和UI线程的通信,主要是用来更新UI。

2.2 API调用源码分析

抄了一份上面转载博客的代码

 public class TestHandlerActivity extends AppCompatActivity {private static final String TAG = "TestHandlerActivity";private Handler mHandler = new Handler(){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);//获得刚才发送的Message对象,然后在这里进行UI操作Log.e(TAG,"------------> msg.what = " + msg.what);}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_handler_test);initData();}private void initData() {//开启一个线程模拟处理耗时的操作new Thread(new Runnable() {@Overridepublic void run() {SystemClock.sleep(2000);//通过Handler发送一个消息切换回主线程(mHandler所在的线程)mHandler.sendEmptyMessage(0);}}).start();}   

可以看出我们常用的就3个

  1. new handler()
  2. sendEmptyMessage()
  3. handleMessage()

2.2.1 new handler()

/*** Default constructor associates this handler with the {@link Looper} for the* current thread.** If this thread does not have a looper, this handler won't be able to receive messages* so an exception is thrown.*/public Handler() {this(null, false);}/*** Constructor associates this handler with the {@link Looper} for the* current thread and takes a callback interface in which you can handle* messages.** If this thread does not have a looper, this handler won't be able to receive messages* so an exception is thrown.** @param callback The callback interface in which to handle messages, or null.*/public Handler(Callback callback) {this(callback, false);}/*** Use the provided {@link Looper} instead of the default one.** @param looper The looper, must not be null.*/public Handler(Looper looper) {this(looper, null, false);}/*** Use the provided {@link Looper} instead of the default one and take a callback* interface in which to handle messages.** @param looper The looper, must not be null.* @param callback The callback interface in which to handle messages, or null.*/public Handler(Looper looper, Callback callback) {this(looper, callback, false);}/*** Use the {@link Looper} for the current thread* and set whether the handler should be asynchronous.** Handlers are synchronous by default unless this constructor is used to make* one that is strictly asynchronous.** Asynchronous messages represent interrupts or events that do not require global ordering* with respect to synchronous messages.  Asynchronous messages are not subject to* the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.** @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for* each {@link Message} that is sent to it or {@link Runnable} that is posted to it.** @hide*/public Handler(boolean async) {this(null, async);}/*** Use the {@link Looper} for the current thread with the specified callback interface* and set whether the handler should be asynchronous.** Handlers are synchronous by default unless this constructor is used to make* one that is strictly asynchronous.** Asynchronous messages represent interrupts or events that do not require global ordering* with respect to synchronous messages.  Asynchronous messages are not subject to* the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.** @param callback The callback interface in which to handle messages, or null.* @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for* each {@link Message} that is sent to it or {@link Runnable} that is posted to it.** @hide*/public Handler(Callback callback, boolean async) {if (FIND_POTENTIAL_LEAKS) {final Class<? extends Handler> klass = getClass();if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&(klass.getModifiers() & Modifier.STATIC) == 0) {Log.w(TAG, "The following Handler class should be static or leaks might occur: " +klass.getCanonicalName());}}mLooper = Looper.myLooper();if (mLooper == null) {throw new RuntimeException("Can't create handler inside thread that has not called Looper.prepare()");}mQueue = mLooper.mQueue;mCallback = callback;mAsynchronous = async;}/*** Use the provided {@link Looper} instead of the default one and take a callback* interface in which to handle messages.  Also set whether the handler* should be asynchronous.** Handlers are synchronous by default unless this constructor is used to make* one that is strictly asynchronous.** Asynchronous messages represent interrupts or events that do not require global ordering* with respect to synchronous messages.  Asynchronous messages are not subject to* the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.** @param looper The looper, must not be null.* @param callback The callback interface in which to handle messages, or null.* @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for* each {@link Message} that is sent to it or {@link Runnable} that is posted to it.** @hide*/public Handler(Looper looper, Callback callback, boolean async) {mLooper = looper;mQueue = looper.mQueue;mCallback = callback;mAsynchronous = async;}

看着api想起来当时面试官还问我handler是同步的还是异步的,emmmmmm,我当时不知道,现在看了是默认是同步的,但是在构造函数里也可以声明成异步的,面试官真是蔫儿坏。

构造函数其实比较简单,就是初始化四个变量,mLooper, mQueue, mCallback和mAsynchronous。

四个变量的作用mLooper和mQueue大致已经清楚了,至于mCallback应该是对于于消息处理的回调,mAsynchronous是声明handler是否是异步的。

/*** Callback interface you can use when instantiating a Handler to avoid* having to implement your own subclass of Handler.*/public interface Callback {/*** @param msg A {@link android.os.Message Message} object* @return True if no further handling is desired*/public boolean handleMessage(Message msg);}/*** Subclasses must implement this to receive messages.*/public void handleMessage(Message msg) {}/*** Handle system messages here.*/public void dispatchMessage(Message msg) {if (msg.callback != null) {handleCallback(msg);} else {if (mCallback != null) {if (mCallback.handleMessage(msg)) {return;}}handleMessage(msg);}}

从上面的代码来看handler的消息处理是优先调用message自带的callback,其次是调用handler声明时初始化的callback,最后才会调用handler自带的函数,handleMessage。我们通常只会用到handler自带的。

我们再来看下mAsynchronous是在哪里被调用的。

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {msg.target = this;if (mAsynchronous) {msg.setAsynchronous(true);}return queue.enqueueMessage(msg, uptimeMillis);}

恩,如果设置为true,也就是异步的,就会调用Message的setAsynchronous方法。
贴一下Message这个方法的源码。

/*** Sets whether the message is asynchronous, meaning that it is not* subject to {@link Looper} synchronization barriers.* <p>* Certain operations, such as view invalidation, may introduce synchronization* barriers into the {@link Looper}'s message queue to prevent subsequent messages* from being delivered until some condition is met.  In the case of view invalidation,* messages which are posted after a call to {@link android.view.View#invalidate}* are suspended by means of a synchronization barrier until the next frame is* ready to be drawn.  The synchronization barrier ensures that the invalidation* request is completely handled before resuming.* </p><p>* Asynchronous messages are exempt from synchronization barriers.  They typically* represent interrupts, input events, and other signals that must be handled independently* even while other work has been suspended.* </p><p>* Note that asynchronous messages may be delivered out of order with respect to* synchronous messages although they are always delivered in order among themselves.* If the relative order of these messages matters then they probably should not be* asynchronous in the first place.  Use with caution.* </p>** @param async True if the message is asynchronous.** @see #isAsynchronous()*/public void setAsynchronous(boolean async) {if (async) {flags |= FLAG_ASYNCHRONOUS;} else {flags &= ~FLAG_ASYNCHRONOUS;}}

不是很懂这个用法,API里提及了中断、输入事件以及其他需要独立操作的信号。

2019-2-25更新

这里注释讲的很明白了,异步消息可以使消息不受限于同步机制。某些操作比如视图失效,可能引入同步障碍到消息队里里去,以防止及时消息被处理,直到某些条件达成。在视图失效的情况下,在view.invalidate后调用的message会被同步障碍阻塞直到下一帧画好。同步障碍保证了失效请求可以在继续前完成。异步消息免受同步障碍限制。典型代表终端输入和其他必须被独立处理的消息即使其他工作被暂停了。

注意异步消息不依赖于同步消息的顺序,及时它们是按顺序下发的。如果消息的相对顺序重要的话,那么可能不应该使用异步。小心使用。

贴一下view的invalidate方法,用于视图刷新,这里api描述是使整个视图失效,onDraw会随后被调用。

/**
     * Invalidate the whole view. If the view is visible,
     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
     * the future.
     * <p>
     * This must be called from a UI thread. To call from a non-UI thread, call
     * {@link #postInvalidate()}.
     */
    public void invalidate() {
        invalidate(true);
    }

2.2.2 sendEmptyMessage

/*** Sends a Message containing only the what value.*  * @return Returns true if the message was successfully placed in to the *         message queue.  Returns false on failure, usually because the*         looper processing the message queue is exiting.*/public final boolean sendEmptyMessage(int what){return sendEmptyMessageDelayed(what, 0);}/*** Sends a Message containing only the what value, to be delivered* after the specified amount of time elapses.* @see #sendMessageDelayed(android.os.Message, long) * * @return Returns true if the message was successfully placed in to the *         message queue.  Returns false on failure, usually because the*         looper processing the message queue is exiting.*/public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {Message msg = Message.obtain();msg.what = what;return sendMessageDelayed(msg, delayMillis);}/*** Enqueue a message into the message queue after all pending messages* before the absolute time (in milliseconds) <var>uptimeMillis</var>.* <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>* Time spent in deep sleep will add an additional delay to execution.* You will receive it in {@link #handleMessage}, in the thread attached* to this handler.* * @param uptimeMillis The absolute time at which the message should be*         delivered, using the*         {@link android.os.SystemClock#uptimeMillis} time-base.*         * @return Returns true if the message was successfully placed in to the *         message queue.  Returns false on failure, usually because the*         looper processing the message queue is exiting.  Note that a*         result of true does not mean the message will be processed -- if*         the looper is quit before the delivery time of the message*         occurs then the message will be dropped.*/public boolean sendMessageAtTime(Message msg, long uptimeMillis) {MessageQueue queue = mQueue;if (queue == null) {RuntimeException e = new RuntimeException(this + " sendMessageAtTime() called with no mQueue");Log.w("Looper", e.getMessage(), e);return false;}return enqueueMessage(queue, msg, uptimeMillis);}private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {msg.target = this;if (mAsynchronous) {msg.setAsynchronous(true);}return queue.enqueueMessage(msg, uptimeMillis);}

这个api调用到最后调用到了MessageQueue的enqueueMessage方法,传递了msg和延时两个参数。下面就是MessageQueue的API了。

boolean enqueueMessage(Message msg, long when) {if (msg.target == null) {throw new IllegalArgumentException("Message must have a target.");}if (msg.isInUse()) {throw new IllegalStateException(msg + " This message is already in use.");}synchronized (this) {if (mQuitting) {IllegalStateException e = new IllegalStateException(msg.target + " sending message to a Handler on a dead thread");Log.w(TAG, e.getMessage(), e);msg.recycle();return false;}msg.markInUse();msg.when = when;Message p = mMessages;boolean needWake;if (p == null || when == 0 || when < p.when) {// New head, wake up the event queue if blocked.msg.next = p;mMessages = msg;needWake = mBlocked;} else {// Inserted within the middle of the queue.  Usually we don't have to wake// up the event queue unless there is a barrier at the head of the queue// and the message is the earliest asynchronous message in the queue.needWake = mBlocked && p.target == null && msg.isAsynchronous();Message prev;for (;;) {prev = p;p = p.next;if (p == null || when < p.when) {break;}if (needWake && p.isAsynchronous()) {needWake = false;}}msg.next = p; // invariant: p == prev.nextprev.next = msg;}// We can assume mPtr != 0 because mQuitting is false.if (needWake) {nativeWake(mPtr);}}return true;}

标红的代码我看懂了,其实message Queue是个单向链表,这个链表保存着head,即mMessages,每次handler发送一个消息messageNew过来的时候就遍历一遍这个单向链表,找到最后一个message或者延时比新的messageNew长的第一个,叫做p,然后就将messageNew的next指向p,p本来前面的prev指向messageNew,即msg.next = p,prev.next = msg的含义。这里表明了sendMessage最终就是将新的message按时间顺序放在一个链表的恰当位置等待调用。这时候再结合前面,如果MessageQueue维持的队列是空的,那新来的message就是HEAD,如果新来的message的when 是0或者比head的延时小,则可以插队,插在最前面,其实表达意思和下面是一样的。

2.2.3 handleMessage

前面new Handler()和sendEmptyMessage都是我们主动调用的,handleMessage则是被动调用的,代码流程就不是很好找了。

我们的从下往上找调用流程了。

之前我们说过callback在哪里被用的:

/*** Handle system messages here.*/public void dispatchMessage(Message msg) {if (msg.callback != null) {handleCallback(msg);} else {if (mCallback != null) {if (mCallback.handleMessage(msg)) {return;}}handleMessage(msg);}}

顺着往上找,发现是Looper在loop()方法里主动调用了Hander的dispatchMessage方法。

 /*** Run the message queue in this thread. Be sure to call* {@link #quit()} to end the loop.*/public static void loop() {final Looper me = myLooper();if (me == null) {throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");}final MessageQueue queue = me.mQueue;// Make sure the identity of this thread is that of the local process,// and keep track of what that identity token actually is.Binder.clearCallingIdentity();final long ident = Binder.clearCallingIdentity();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);}final long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;final long traceTag = me.mTraceTag;if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {Trace.traceBegin(traceTag, msg.target.getTraceName(msg));}final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();final long end;try {msg.target.dispatchMessage(msg);end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();} finally {if (traceTag != 0) {Trace.traceEnd(traceTag);}}if (slowDispatchThresholdMs > 0) {final long time = end - start;if (time > slowDispatchThresholdMs) {Slog.w(TAG, "Dispatch took " + time + "ms on "+ Thread.currentThread().getName() + ", h=" +msg.target + " cb=" + msg.callback + " msg=" + msg.what);}}if (logging != null) {logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);}// Make sure that during the course of dispatching the// identity of the thread wasn't 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();}}emmmmm,大致流程已经和开头的图对上了,handler维持一个messageQueue,用于存储handler发送来的message队列,Looper用于轮询messageQueue取出消息,调用handler的handleMessage进行处理,当然有可能是callback或者message的callback的handleMessage方法啦。

Looper开头的注释也很有意思,子线程调用hander的时候必须调用Looper.prepare()进行初始化,调用Looper.loop()进行消息队列的处理。

/*** Class used to run a message loop for a thread.  Threads by default do* not have a message loop associated with them; to create one, call* {@link #prepare} in the thread that is to run the loop, and then* {@link #loop} to have it process messages until the loop is stopped.** <p>Most interaction with a message loop is through the* {@link Handler} class.** <p>This is a typical example of the implementation of a Looper thread,* using the separation of {@link #prepare} and {@link #loop} to create an* initial Handler to communicate with the Looper.** <pre>*  class LooperThread extends Thread {*      public Handler mHandler;**      public void run() {*          Looper.prepare();**          mHandler = new Handler() {*              public void handleMessage(Message msg) {*                  // process incoming messages here*              }*          };**          Looper.loop();*      }*  }</pre>*/

而UI线程不用是由于ActivityThread.java已经在main()里帮我们调用好了。

Activity中有个ActivityThread mMainThread的成员变量,这块后续还要再看下,不是很懂。

public static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");// CloseGuard defaults to true and can be quite spammy.  We// disable it here, but selectively enable it later (via// StrictMode) on debug builds, but using DropBox, not logs.CloseGuard.setEnabled(false);Environment.initForCurrentUser();// Set the reporter for event logging in libcoreEventLogger.setReporter(new EventLoggingReporter());// Make sure TrustedCertificateStore looks in the right place for CA certificatesfinal File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());TrustedCertificateStore.setDefaultUserDirectory(configDir);Process.setArgV0("<pre-initialized>");Looper.prepareMainLooper();ActivityThread thread = new ActivityThread();thread.attach(false);if (sMainThreadHandler == null) {sMainThreadHandler = thread.getHandler();}if (false) {Looper.myLooper().setMessageLogging(newLogPrinter(Log.DEBUG, "ActivityThread"));}// End of event ActivityThreadMain.Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");}
MessageQueue的next()方法也比较有意思,轮询,如果延时还没到,那就等一会,如果延时到了,返回相应的message,给looper。
 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) {// Stalled by a barrier.  Find the next asynchronous message in the queue.do {prevMsg = msg;msg = msg.next;} while (msg != null && !msg.isAsynchronous());}if (msg != null) {if (now < msg.when) {// 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.if (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;}}

3.总结:

再贴一下下面的图,下面的图讲的很透彻了=-=

(一)Handler相关推荐

  1. 为什么UI线程中创建Handler可以不传Looper?

    一个APP程序的入口是ActivityThread的main方法,ActivityThread就是我们常说的主线程或UI线程,事实上它并不是一个线程,而是主线程操作的管理者. public stati ...

  2. Android中Handler消息机制

    作用:跨线程通信. 应用:AsyncTask.retrofit都对Handler进行了封装. 四要素:Message.MessageQueue.Looper.Handler Message简介: 线程 ...

  3. Python:urllib2模块Handler处理器 和 自定义Opener

    Handler处理器 和 自定义Opener opener是 urllib2.OpenerDirector 的实例,我们之前一直都在使用的urlopen,它是一个特殊的opener(也就是模块帮我们构 ...

  4. Android Handler sendMessage和 sendMessageDelayed的使用

    sendMessage :立即发送消息 sendMessageDelayed:指定多少毫秒后发送消息. 其实常用的还有2个 sendEmptyMessage 发送空消息,  一般自己想把某种操作放到子 ...

  5. Handler 实现的一个循环操作

    这个使用Handler 实现的一个循环操作还是比较简单的,下面就直接给出demo了 一个间隔5s 弹一次Toast 的demo 如下 public class MainActivity extends ...

  6. Handler 实现的一个延时操作

    今天回顾下handler 记录一个延时的demo 使用 postDelayed 主要代码如下: public class MainActivity extends AppCompatActivity ...

  7. Android 实现一个验证码倒计时(Handler postDelayed 实现验证码倒计时)

    直接看代码吧,很简单 public class MainActivity extends AppCompatActivity {private TextView code;private Handle ...

  8. Android Handler sendEmptyMessageDelayed 和 sendEmptyMessage 的使用

    sendEmptyMessage 发送空消息 sendEmptyMessageDelayed 指定多少毫秒后发送空消息 常用的还有2个如下 sendMessage :立即发送消息 sendMessag ...

  9. Handler的postDelayed()关闭的方法

    关闭的方法主要使用removeCallbacks,下面举一个demo 说明 使用方法: 1,首先创建一个Handler对象 Handler handler=new Handler(); 2,然后创建一 ...

  10. Spring MVC-处理程序映射(Handler Mapping)-简单的Url处理程序映射(Simple Url Handler Mapping)示例(转载实践)...

    以下内容翻译自:https://www.tutorialspoint.com/springmvc/springmvc_simpleurlhandlermapping.htm 说明:示例基于Spring ...

最新文章

  1. oracle层次查询用处,Oracle描述层次查询(hierarchicalquery)
  2. Python3.7环境配置
  3. Java基础语法(数组)
  4. Codeforces940(A-F)
  5. 2018年4月更新70多个公司dnc招聘职位
  6. java中的线程和进程,Java | 线程和进程,创建线程
  7. 【HDU - 1102】Constructing Roads (最小生成树裸题模板)
  8. [hadoop读书笔记] 第十五章 sqoop1.4.6小实验 - 将mysq数据导入hive
  9. 《Cracking the Coding Interview》——第9章:递归和动态规划——题目8
  10. java单一窗体设计模式,JAVA中设计模式之 -- 单例模式
  11. 【华为云技术分享】圣诞特别版 | 数据库频频出现OOM问题该如何化解?
  12. git优点缺点(简单介绍)
  13. linux停止license服务器,LICENSE · 机器不学习/linux-command - Gitee.com
  14. 【Python】9×9数独计算器
  15. 远程桌面连接:使用lcx进行端口转发
  16. speak 计算机英语作文,【必备】英语作文5篇
  17. 史上最难的初等几何问题?分享一个参考答案
  18. 【数据结构】二叉树经典习题
  19. 哈希表——线性探测法、链地址法、查找成功、查找不成功的平均长度
  20. python 矩阵求转置、行列式、迹、求逆

热门文章

  1. 云计价i20工程总承包计价软件【十问十答】
  2. MongoDB基础-快速入门
  3. 【学习】网页设计技术 - 在线复习题
  4. 66道前端算法面试题附思路分析助你查漏补缺
  5. C#——对象转换为JSON格式的字符串
  6. 游戏接入华为SDK4.0(记录:实名认证问题、错误码查询和支付/游戏/账号demo下载地址)
  7. 联发科P70相比P60升级有限,有点不思进取
  8. Java实现 LeetCode 413 等差数列划分
  9. maya里的substance节点使用
  10. leetcode投骰子问题动态规划