Android之消息机制(三)源码解析

Android之消息机制(三)源码解析

干货,非常干。。。

目录

一、概述

二、源码

2.1 Message源码

2.1.1 实现序列化

2.1.2 obtain()方法,消息池中取消息,以链表实现队列;

2.1.3 Message的recycle(),用于回收消息,时机是在Looper.loop()方法中,执行完Handler处理后。

2.2 MessageQueue源码

2.2.1 next()方法通过when时间来取元素

2.3 Looper源码

2.3.1 prepare(),其实是采用ThreadLocal来解决线程同步的问题(TheadLocal是Looper的成员变量);使用ThreadLocal连接了某线程和Looper对象;

2.3.2 Loop(),循环处理消息

2.3.3 quit(),会调用MessageQueue中的quit()将消息队列中消息置空,然后Looper.loop()时

2.4 Handler源码

2.4.1 sendMessage(),发送消息

2.4.2 dispatchMessage()方法,处理消息事件

三、小结


 

一、概述

Looper不停从MessageQueue中取Message,MessageQueue是在Looper中的(MessageQueue是Looper的一个成员变量);

 

Message实现了Parceable(以便序列化,因为有时会需要进程间通信而去传递Message)

 

消息池,Message的obtain方法,用链表的方式实现池,首先取第一个元素,而让首指针指向下一个元素即可。

 

Looper中loop方法

for(;;){Message msg = queue.next();msg.target.dispatchMessage(msg);}

msg.target即为handler,每一个Message都持有一个发送者Handler的引用。

 

Looper.prepare()方法

调用ThreadLocal.set(Looper),ThreadLocal保证了线程安全,不让其他线程去获取主线程的Looper;

ThreadLocal(Values类似HashMap),通过ThreadLocal将Thread与Looper进行绑定;

ThreadLocal.put(this,values)

this为Looper对象,values可以用来拿当前Thread,保持唯一Thread

 

Handler声明在哪里,拿到的Looper就是该线程的Looper

Handler中会有mlooper=Looper.myLooper(),myLooper()就是会ThreadLocal中取values。

 

应用的运行,ActivityThread的looper.loop()后,如何改变主线程的执行?

通过新增Message去改变。

 

二、源码

2.1 Message源码

2.1.1 实现序列化

public final class Message implements Parcelable

2.1.2 obtain()方法,消息池中取消息,以链表实现队列;

public static Message obtain() {

synchronized (sPoolSync) {

if (sPool != null) {

Message m = sPool;

sPool = m.next;

m.next = null;

m.flags = 0; // clear in-use flag

sPoolSize--;

return m;

}

}

return new Message();

}

消息池中有消息就去取(以链表的方式取头指针的Message),没有消息就new出来.

 

2.1.3 Message的recycle(),用于回收消息,时机是在Looper.loop()方法中,执行完Handler处理后。

public void recycle() {

if (isInUse()) {

if (gCheckRecycle) {

throw new IllegalStateException("This message cannot be recycled because it "

+ "is still in use.");

}

return;

}

recycleUnchecked();

}

 

void recycleUnchecked() {

// Mark the message as in use while it remains in the recycled object pool.

// Clear out all other details.

flags = FLAG_IN_USE;

what = 0;

arg1 = 0;

arg2 = 0;

obj = null;

replyTo = null;

sendingUid = -1;

when = 0;

target = null;

callback = null;

data = null;

 

synchronized (sPoolSync) {

if (sPoolSize < MAX_POOL_SIZE) {

next = sPool;

sPool = this;

sPoolSize++;

}

}

}

 

其实看得出也是把该Message的属性进行重置,然后把该Message放到消息池的头指针上。

 

2.2 MessageQueue源码

2.2.1 next()方法通过when时间来取元素

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 (false) Log.v("MessageQueue", "Returning message: " + msg);

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("MessageQueue", "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;

}

}

 

核心代码主要是

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 (false) Log.v("MessageQueue", "Returning message: " + msg);

return msg;

}

找出when比当前时间小的Message,通过断链的方式将其取出来。

 

 

2.3 Looper源码

2.3.1 prepare(),其实是采用ThreadLocal来解决线程同步的问题(TheadLocal是Looper的成员变量);使用ThreadLocal连接了某线程和Looper对象;

public static void prepare() {

prepare(true);

}

 

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

}

 

2.3.2 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

Printer logging = me.mLogging;

if (logging != null) {

logging.println(">>>>> Dispatching to " + msg.target + " " +

msg.callback + ": " + msg.what);

}

 

msg.target.dispatchMessage(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 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();

}

}

关键点是Message msg = queue.next(); // might block取出消息,然后,msg.target.dispatchMessage(msg);其中msg.target就是handler,这里就是进行handler处理消息,

最后处理完msg后,msg.recycleUnchecked();对消息进行回收。

 

2.3.3 quit(),会调用MessageQueue中的quit()将消息队列中消息置空,然后Looper.loop()时

if (msg == null) {

// No message indicates that the message queue is quitting.

return;

}

则会跳出Looper.loop()的循环;

public void quit() {

mQueue.quit(false);

}

 

MessageQuue中代码

void quit(boolean safe) {

if (!mQuitAllowed) {

throw new IllegalStateException("Main thread not allowed to quit.");

}

 

synchronized (this) {

if (mQuitting) {

return;

}

mQuitting = true;

 

if (safe) {

removeAllFutureMessagesLocked();

} else {

removeAllMessagesLocked();

}

 

// We can assume mPtr != 0 because mQuitting was previously false.

nativeWake(mPtr);

}

}

 

然后会执行 removeAllMessagesLocked();

 

private void removeAllMessagesLocked() {

Message p = mMessages;

while (p != null) {

Message n = p.next;

p.recycleUnchecked();

p = n;

}

mMessages = null;

}

将所有的Message全部进行消息置空且回收。

 

2.4 Handler源码

2.4.1 sendMessage(),发送消息

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

}

则会去调用MessageQueue的enqueueMessage(msg, uptimeMillis)方法

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("MessageQueue", 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插入到队列的尾部。

 

2.4.2 dispatchMessage()方法,处理消息事件

Looper.loop()会去调用Handler的dispatchMessage()方法,

public void dispatchMessage(Message msg) {

if (msg.callback != null) {

handleCallback(msg);

} else {

if (mCallback != null) {

if (mCallback.handleMessage(msg)) {

return;

}

}

handleMessage(msg);

}

}

通常会采用handleMessage(msg)的方式,当然也可以采用Handler的post(Runnable r)的方式,那么其实调用的就是handleCallback(msg);

 

三、小结

以上源码如果看的云里雾里的话,可以考虑重点观察这条主线Looper.loop()的方法。

Looper.loop()就是从MessageQueue中得到下一个Message(MessageQueue的next()方法),取出的message通过调用msg.target(也就是handler)去执行dispatchMessage()方法,执行完毕后调用了message的recycle()方法进行回收以便从消息池去取出。

 

你可能感兴趣的:(Android应用开发基础)