Android源码解析——Handler,定制移动app

public static void main(String[] args) {

···

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 对象已经由系统来为我们初始化好了,那我们就可以从中得到 mQueue对象

public Handler(Callback callback, boolean async) {

···

mLooper = Looper.myLooper();

if (mLooper == null) {

throw new RuntimeException(

“Can’t create handler inside thread that has not called Looper.prepare()”);

}

//获取 MessageQueue 对象

mQueue = mLooper.mQueue;

mCallback = callback;

mAsynchronous = async;

}

mQueue 又是在 Looper 类的构造函数中初始化的,且 mQueue 是 Looper 类的成员常量,这说明 Looper 与 MessageQueue 是一一对应的关系

private Looper(boolean quitAllowed) {

mQueue = new MessageQueue(quitAllowed);

mThread = Thread.currentThread();

}

sendMessageAtTime() 方法中在处理 Message 时,最终调用的是 enqueueMessage() 方法

当中,需要注意 msg.target = this 这句代码,target 对象指向了发送消息的主体,即 Handler 对象本身,即由 Handler 对象发给 MessageQueue 的消息最后还是要交由 Handler 对象本身来处理

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

//target 对象指向的也是发送消息的主体,即 Handler 对象

//即由 Handler 对象发给 MessageQueue 的消息最后还是要交由 Handler 对象本身来处理

msg.target = this;

if (mAsynchronous) {

msg.setAsynchronous(true);

}

return queue.enqueueMessage(msg, uptimeMillis);

}

因为存在多个线程同时往同一个 Loop 线程的 MessageQueue 中插入消息的可能,所以 enqueueMessage() 内部需要进行同步。可以看出 MessageQueue 内部是以链表的结构来存储 Message 的(Message.next),根据 Message 的延时时间的长短来将决定其在消息队列中的位置

mMessages 代表的是消息队列中的第一条消息,如果 mMessages 为空,说明消息队列是空的,或者 mMessages 的触发时间要比新消息晚,则将新消息插入消息队列的头部;如果 mMessages 不为空,则寻找消息列队中第一条触发时间比新消息晚的非空消息,并将新消息插到该消息前面

到此,一个按照处理时间进行排序的消息队列就完成了,后边要做的就是从消息队列中依次取出消息进行处理了

boolean enqueueMessage(Message msg, long when) {

//Message 必须有处理者

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 deadAndroid源码解析——Handler,定制移动app_第1张图片
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;

}

下面再看下 MessageQueue 是如何读取 Message 并回调给 Handler 的

在 MessageQueue 中消息的读取其实是通过内部的 next() 方法进行的,next() 方法是一个无限循环的方法,如果消息队列中没有消息,则该方法会一直阻塞,当有新消息来的时候 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;

}

}

next() 方法又是通过 Looper 类的 loop() 方法来循环调用的,而 loop() 方法也是一个无限循环,唯一跳出循环的条件就是 queue.next() 方法返回为null ,细心的读者可能已经发现了,loop() 就是在 ActivityThread 的 main()函数中调用的

因为 next() 方法是一个阻塞操作,所以当没有消息也会导致 loop() 方法一只阻塞着,而当 MessageQueue 一中有了新的消息,Looper 就会及时地处理这条消息并调用 Message.target.dispatchMessage(Message) 方法将消息传回给 Handler 进行处理

/**

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

}

}

看下 Handler 对象处理消息的方法

/**

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

}

}

如果 msg.callback 不为 null ,则调用 callback 对象的 run() 方法,该 callback 实际上就是一个 Runnable 对象,对应的是 Handler 对象的 post() 方法

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

}

}

看下 Handler 对象处理消息的方法

/**

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

}

}

如果 msg.callback 不为 null ,则调用 callback 对象的 run() 方法,该 callback 实际上就是一个 Runnable 对象,对应的是 Handler 对象的 post() 方法

你可能感兴趣的:(程序员,架构,移动开发,android)