代码分析:Android中Handler机制---Handler与Thread

Handler机制中最重要的元素包括:Thread,Looper,Handler,MessageQueue,Message五大元素。

Android中主线程和子线程通信,常会使用到Handler,而Handler内部是如何工作呢?

首先,执行在子线程中的代码是指运行于run方法中的代码,而不是我们继承Thread中所有的代码。

在子线程中使用Handler机制有2个重要的方法Looper.prepare()和Looper.loop()。我们需要在线程中先调用Looper.prepare()才能创建Handler对象,然后在线程最后调用Looper.loop()消息才能执行。

Looper.prepare()中是执行Looper的创建并且使用ThreadLocal保存,限制一个线程中只能存在一个Looper对象。

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

}

一旦在线程中重复创建Looper对象的话就会抛出异常。而在Looper的构造方法中

private Looper(boolean quitAllowed) {

mQueue = new MessageQueue(quitAllowed);

mThread = Thread.currentThread();

}

首先创建了一个MessageQueue对象,再讲线程和Looper挂上钩。

创建好Looper对象之后,才能创建Handler,那这是为什么呢?在Handler的构造方法中:

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;

当Looper对象为空直接抛异常,然后在将Hanler拿到MessageQueue的引用。

然后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 traceTag = me.mTraceTag;

if (traceTag != 0) {

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

}

}

首先loop中会先拿到线程中对应的Looper对象,然后获取MessageQueue并且进入无线循环读取Message并且执行Message的任务。

到此Looper对象的职责就清晰明了了,首先和线程一一对应,保证了线程中只有一个MessageQueue,以及进入一个无限循环读取执行消息。

Handler在创建的时候拿到线程中的Looper,而后获取MessageQueue对象,而在sendMessage以及postDelayed都会执行到enqueueMessage中向MessageQueue中添加消息。

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {

msg.target = this;

if (mAsynchronous) {

msg.setAsynchronous(true);

}

return queue.enqueueMessage(msg, uptimeMillis);

}

在loop方法中,Message是通过target执行dispatchMessage方法处理消息。

msg.target.dispatchMessage(msg);

而target方法是Handler对象,在构建消息的时候,Message会在创建的时候传入target。

public static Message obtain(Handler h, Runnable callback) {

Message m = obtain();

m.target = h;

m.callback = callback;

return m;

}

当然这个传入的Handler没什么用,因为最终message的target在添加到对应的MessageQueue前都会将target指向发送Message的Handler。

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {

msg.target = this;

if (mAsynchronous) {

msg.setAsynchronous(true);

}

return queue.enqueueMessage(msg, uptimeMillis);

}

最终回到消息处理回到Handler的dispatchMessage中。

public void dispatchMessage(Message msg) {

if (msg.callback != null) {

handleCallback(msg);

} else {

if (mCallback != null) {

if (mCallback.handleMessage(msg)) {

return;

}

}

handleMessage(msg);

}

}

Handler的职责就是将Message添加到MessageQueue并且最终处理Message。

MessageQueue的职责是保存Message,并且在对应的时间给Thread处理Message,而在MessageQueue中没有即时消息,就会使线程进入阻塞。

Message就是一个消息体。

你可能感兴趣的:(代码分析:Android中Handler机制---Handler与Thread)