先来看一下Handler的基本流程:
(1)先分析第一部分的代码 Looper.prepare():
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));
if ( sThreadLocal.get() != null) {
throw new RuntimeException( "Only one Looper may be created per thread");
}
sThreadLocal.set( new Looper(quitAllowed));
}
可以看到就是创建一个Looper对象,然后存入ThreadLocal对象中,同时也就实现了每个线程都有相互独立Looper
(2)Looper.loop()
/**
* 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
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();
* 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
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();
}
}
loop();开始调用以后就进入了死循环
并且不断获取下一个Message,
再将Message交给它的target的dispatchMessage方法进行处理。
(3)new Handler()
public Handler() {
this( null, false);
}
this( null, false);
}
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;
}
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;
}
我们来看看 new Handler()到底做了什么,
其实就是获得当前线程的Looper,使得Handler与Looper进行绑定,这是默认的实现。
同时也有带有Looper的构造函数,这就代表了Handler其实可以绑定其他线程的Looper。
(4)post消息
public final boolean
sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
{
return sendMessageDelayed(msg, 0);
}
public final boolean
sendMessageDelayed(Message msg,
long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock. uptimeMillis() + 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);
}
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) {
msg.target = this;
if ( mAsynchronous) {
msg.setAsynchronous( true);
}
return queue.enqueueMessage(msg, uptimeMillis);
msg.target = this;
if ( mAsynchronous) {
msg.setAsynchronous( true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
可以看到在Handler中最终调用的就是将消息放入消息队列的方法
queue.enqueueMessage(msg, uptimeMillis);
总结:
最后,通过简单的学习几个相关类的源码,我们就可以试着理解为什么平时我们可以用Handler来解决子线程里更新UI的问题了:
(1)首先我们在主线程中 newHandler 绑定到了主线程中的Looper
(2)post出去的消息也就发到了UI线程中Looper的消息队列中
(3)Looper循环处理Message中的消息其实是回调了 Handler中的处理方法
(4)同时Looper是在它绑定的的线程里执行处理方法的,其实就相当于在UI线程中执行了处理代码,也就可以更新UI了。
这样Handler的原理是基本打通了,但是有很多细节还没能深入学习,一部分是因为再往下层涉及到的东西我还没看懂,估计还需要一段时间,所以先把阶段性的成果先放出来