Handler、Looper、MessageQueue源码分析

2012年5月9日10:12:33 发表评论 19 views

1、概述

Handler,looper,MessageQueue贯穿整个App生命周期,本篇文章从app入口ActivityThread开始讲述整个Handler原理机制。

2、原理分析

我们先从app启动类ActivityThread分析Handler机制

public static void main(String[] args) {
     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
     SamplingProfilerIntegration.start();
     // 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 libcore
     EventLogger.setReporter(new EventLoggingReporter());
     // Make sure TrustedCertificateStore looks in the right place for CA certificates
     final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
     TrustedCertificateStore.setDefaultUserDirectory(configDir);
     Process.setArgV0("<pre-initialized>");
     //looper初始化准备
     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");
}

在上面可以看到整个App启动时开启Looer.loop()循环后就new RuntimeException(),由此可知在Loop.loop()以后正常时程序将阻塞,但是我们开发App时事件是怎么传递主线程?我们先分析Looper.prepareMainLooper()这个方法

public static void prepareMainLooper() {
    prepare(false);
    synchronized (Looper.class) {
        if (sMainLooper != null) {
             throw new IllegalStateException("The main Looper has already been prepared.");
        }
        sMainLooper = myLooper();
    }
}

在ActivityThread中调用的是Looper.prepareMainLooper()方法,在这个方法中调用prepare(false)方法我们跳转到prepare(false)可以看到

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));
}

在此时会查看ThreadLocal中是否有当前Looper,在此解释下ThreadLocal,ThreadLocal是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,数据存储以后,只有在指定线程中可以获取到存储的数据,对于其它线程来说无法获取到数据。当前线程为主线程,looper此时没有初始化放到ThreadLocal中,所以sThreadLocal.get()此时为空,接下来创建Looper并且放入到ThreadLocal中,我们来看下Looper的构造方法

private Looper(boolean quitAllowed) {
       mQueue = new MessageQueue(quitAllowed);
       mThread = Thread.currentThread();
}

在创建Looper时会初始化MessageQueue,并且保存当前的线程(重要,后面说明)。到此我们可以看到Looper.prepareMainLooper()整个流程。

再看我们创建Handler通过Handler发送消息,

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;
}

通过Handler构造会发现调用Looper.myLooper()方法,获取ThreadLocal中Looper对象,如果为空抛出Can’t create handler inside thread that has not called Looper.prepare(),这也就是在子线程中直接创建Handler会抛出的异常,子线程和主线程访问ThreadLocal获取的Looper不同,所以在子线程中创建Handler时要先调用Looper.prepare()方法创建Looper对象并且放在以子线程为key的ThreadLocal中。通过ThreadLoack.get()方法获取。mLooper.mQueue是我们刚才分析的Looper.prepareMainLooper()中创建Looper对象时会创建MessageQueue对象。当我们在子线程中通过Handler.sendMessage(Message msg)方法:

public final Boolean sendMessage(Message msg)
{
	return sendMessageDelayed(msg, 0);
}

此时会看到发送一个延时0秒的消息

public final boolean sendMessageDelayed(Message msg, long delayMillis)
 {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}

此时获取当前时间加上延时时间得到消息发送的时间

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);
}

queue是我们创建Looper时创建的对象,

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

在此时把当前的Handler设置给Message,调用MessageQueue把Message加入到消息队列中,

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.next
			prev.next = msg;
		}
		// We can assume mPtr != 0 because mQuitting is false.
		if (needWake) {
			nativeWake(mPtr);
		}
	}
	return true;
}

msg.target获取Handler对象, Message p = mMessages保存mMessage,后面接收mMessage的用途,第一次加入队列是mMessage为空,把刚发送的msg.next置位空(mMessage此时为空),把msg赋值给mMessage,此时如果Looper.loop()没有执行,当再次通过Handler发送消息时,mMessage此时不为空,声明一个上一个Message prev,把上次加入队列的mMessage((上次加入对列叫Message1))赋值给prev,判断上次mMessage的下个节点是否为null,为空跳出循环,把第二次加入队列的Message的下个节点赋值为空(msg.next=p 此时p为空),然后把第一次加入对列的Message的下个节点赋值为第二次添加Message(prev.next=msg);因此此时Message的节点为Message1.next=Message2,Message2.next=null,成链表结构

第一次添加Message如图:
Handler、Looper、MessageQueue源码分析

第二次添加Message如图:
Handler、Looper、MessageQueue源码分析

我们再来看下Looper.loop()方法循环获取MessageQueue对列中消息

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 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
		final Printer logging = me.mLogging;
		if (logging != null) {
			logging.println(">>>>> Dispatching to " + msg.target + " " +
			                            msg.callback + ": " + msg.what);
		}
		final long traceTag = me.mTraceTag;
		if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
			Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
		}
		try {
			msg.target.dispatchMessage(msg);
		}
		finally {
			if (traceTag != 0) {
				Trace.traceEnd(traceTag);
			}
		}
		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();
	}
}

在循环Looper时先调用myLooper()方法获取Looper对象,

public static @Nullable Looper myLooper() 
{
         return sThreadLocal.get();
}

此时从ThreadLocal获取looper对象,在Looper.prepare()时把Looper对象放入ThreadLocal中(前面有描述),调用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 iteration
	int 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 handler
			Boolean 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;
	}
}

获取mMessage(Message msg = mMessages),mMessage存储的是第一个Message对象,声明一个变量保存前一个Message(prevMsg=msg),获取当前Message.next节点(第一次为mMessage也就是最先添加到MessageQueue对列的消息),不断获取下一个节点,直到获取到最后一次添加到MessageQueue的消息,判断当前时间是否小于Message设置的时间(handler.sendMessage()的时间加延时时间),如果等于Message设置的时间,当前是最后一次添加Message,所以Message.next为null,设置倒数第二次的next节点为null(删除最后一个节点),返回最后一个节点Message,调用msg.target.dispatchMessage(msg)方法,msg.targer为Handler对象的dispatchMessage()方法,在dispatchMessage()调用handleMessage(msg)方法,我们在创建Handler时重写handlerMessage方法.到此子线程中切换到主线程完成。还有一点补充,子线程中可以调用主线程中创建的handler方法,是因为在创建子线程时会创建任务栈把主线程中的数据拷贝一份,所有子线程中可以访问handler和Activity,因此在使用handler时可以用软引用包裹。

3、总结

在ActivityThread中系统调用Looper.prepareMainLooper方法,创建Looper对象,并且在Looper对象中创建MessageQueue对象,然后调用Looper.loop()方法循环获取MessageQueue中的消息,我在程序中创建Handler对象时,应为是在主线程中创建所以ThreadLocal中保存了Looper对象,没有抛Can’t create handler inside thread that has not called Looper.prepare()异常,当我们在子线程中通过Handler.sendMessage时调用Handler.sendMessageAtTime()发送一个当前时间+延时时间组成Message需要处理的毫秒时间,把Handler赋值给Message.tag,加入到MessageQueue中,MessageQueue中维持一个Message链表,每次把消息节点插入到最后,Looper.loop会循环读取MessageQueue的Message。

  • yiisaa
  • 这是我的微信扫一扫
  • weinxin
  • zhengweiqiangcom
  • 我的微信公众号扫一扫
  • weinxin

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: