Android的消息机制就是指Handler机制,今天分析Handler的源码
从sendMessage方法看起
public final boolean
sendMessage(Message msg)
{
return
sendMessageDelayed(msg,
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);
}
可以看到,这里执行了enqueueMessage,点进去
private boolean
enqueueMessage(MessageQueue queue, Message msg,
long
uptimeMillis) {
msg.target =
this
;
if
(
mAsynchronous
) {
msg.setAsynchronous(
true
);
}
return
queue.enqueueMessage(msg, uptimeMillis);
}
可以看到这里是调用了queue的enqueueMessage,就是把message加入消息队列
继续看equeueMessage的实现,这个具体实现是在MessageQueue里面
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
;
}
这里就是将message插入队列中,这里还有点看不明白
Looper会执行loop(),不断的从MessageQueue中取消息,获取到消息后会执行Handler的dispatchMessage方法
现在的疑问是loop在哪里调用执行的?
答案是主线程是默认有消息队列的,在ActivityThread的main方法中可以看到
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 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.
prepareMainLooper
();
ActivityThread thread =
new
ActivityThread();
thread.attach(
false
);
if
(
sMainThreadHandler
==
null
) {
sMainThreadHandler
= thread.getHandler();
}
if
(
false
) {
Looper.
myLooper
().setMessageLogging(
new
LogPrinter(Log.
DEBUG
,
"ActivityThread"
));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.
loop
();
throw new
RuntimeException(
"Main thread loop unexpectedly exited"
);
}
这里调用了Looper.prepareMainLooper和Looper.loop();
但是如果要自己在子线程中创建Handler的话,就要自己调用Looper.prepare()和Looper.loop()方法
继续看下Looper的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 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
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();
}
}
可以看到loop里有一个for死循环,就是一直取消息,取到消息后就执行msg.target.dispatchMessage方法,即Handler的dispatchMessage方法
参考