classLooperThreadextendsThread { public Handler mHandler; publicvoidrun() { Looper.prepare(); mHandler = newHandler() { publicvoidhandleMessage(Message msg) { // process incoming messages here } }; Looper.loop(); } }
具体分析
初始化过程
Handler构造方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
publicHandler(Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { final Class<? extendsHandler> 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(); //这里从Looper中获取mLooper对象,如果为空则抛出异常 if (mLooper == null) { thrownewRuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue;//从Looper中获取消息队列 mCallback = callback;//callback赋值 mAsynchronous = async;//是否是同步处理消息 }
publicstaticfinalvoidprepare() { if (sThreadLocal.get() != null) { thrownewRuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(newLooper()); }
publicstaticvoidloop() { finalLooperme= myLooper(); if (me == null) { thrownewRuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } finalMessageQueuequeue= 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(); finallongident= Binder.clearCallingIdentity();
for (;;) { //这里单链表中获取消息一直是循环的,当没有消息时这里会阻塞住,进入休眠状态等待再有消息后唤醒 Messagemsg= queue.next(); // might block if (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 logger finalPrinterlogging= me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } //这里有一个执行耗时阈值的检测,统计执行时间差如果超过阈值会进行打印,并获取堆栈信息 finallongslowDispatchThresholdMs= me.mSlowDispatchThresholdMs;
finallongtraceTag= me.mTraceTag; if (traceTag != 0 && Trace.isTagEnabled(traceTag)) { Trace.traceBegin(traceTag, msg.target.getTraceName(msg)); } finallongstart= (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis(); finallong end; try { //开始调用target的dispatchMessage来分发消息 msg.target.dispatchMessage(msg); end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis(); } finally { if (traceTag != 0) { Trace.traceEnd(traceTag); } } if (slowDispatchThresholdMs > 0) { finallongtime= 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. finallongnewIdent= 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); }
/** * Callback interface you can use when instantiating a Handler to avoid * having to implement your own subclass of Handler. * * @param msg A {@link android.os.Message Message} object * @return True if no further handling is desired */ publicinterfaceCallback { publicbooleanhandleMessage(Message msg); }
/** * Subclasses must implement this to receive messages. */ publicvoidhandleMessage(Message msg) { }
synchronized (this) { // Try to retrieve the next message. Return if found. finallongnow= SystemClock.uptimeMillis(); MessageprevMsg=null; Messagemsg= mMessages; ... if (msg != null) { if (now < msg.when) { // Next message is not ready. Set a timeout to wake up when it is ready. //设置时间要休眠的时间,让nativePollOnce一段时间后醒过来 nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE); } else { ... return msg; } } ... } }
privateintpostSyncBarrier(long when) { // Enqueue a new sync barrier token. // We don't need to wake the queue because the purpose of a barrier is to stall it. synchronized (this) { finalinttoken= mNextBarrierToken++; finalMessagemsg= Message.obtain(); msg.markInUse(); msg.when = when; msg.arg1 = token; //按照时间顺序将消息插入到消息队列中 ...... return token; } }
/** * Return a new Message instance from the global pool. Allows us to * avoid allocating new objects in many cases. */ publicstatic Message obtain() { synchronized (sPoolSync) { if (sPool != null) { Messagem= sPool; sPool = m.next; m.next = null; m.flags = 0; // clear in-use flag sPoolSize--; return m; } } returnnewMessage(); }