浅谈 -Android-Handler,h5 移动端开发面试题
Values?values?=?values(currentThread);if?(values?!=?null)?{Object[]?table?=?values.table;int?index?=?hash?&?values.mask;if?(this.reference?==?table[index])?{return?(T)?table[index?+?1];}}?else?{values?=?initializeValues(currentThread);}
return?(T)?values.getAfterMiss(this);}
get 方法就是取出当前线程对应的 looper,也就是说 ThreadLocal 是负责 thread 和 looper 之间的关系的
下面看一下 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));}
默认情况下 ThreadLocal 是没有存储的,所以要创建一个新的 looper
private?Looper(boolean?quitAllowed)?{mQueue?=?new?MessageQueue(quitAllowed);mThread?=?Thread.currentThread();}
默认情况下 ThreadLocal 是没有存储的,所以要创建一个新的 looper
private?Looper(boolean?quitAllowed)?{mQueue?=?new?MessageQueue(quitAllowed);mThread?=?Thread.currentThread();}
![image.gif](https://upload-images.jianshu.io/upl
oad_images/15233854-8187e19d407873b6.gif?imageMogr2/auto-orient/strip)
从 looper 方法中,创建了一个 MessageQueue,在 looper 中维护着一个消息队列
知道了 looper 和 MessageQueue 之后,究竟 handler 跟这两者有什么关系呢,继续看源码
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;}
首先调用 Looper.myLooper()
public?static?@Nullable?Looper?myLooper()?{return?sThreadLocal.get();}
获得当前的 looper 对象,通过 looper 拿到 MessageQueue,就完成了 handler 和 looper 之间的关联
下面继续看 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)?{msg.target?=?this;if?(mAsynchronous)?{msg.setAsynchronous(true);}return?queue.enqueueMessage(msg,?uptimeMillis);}
插入消息之前就指定消息发送给谁(msg.target),默认情况下发送给自己的 handler,然后把消息放入队列中,handler 就完成了发送 message 到 MessageQueue 的过程
那么消息又是如何轮询的呢?
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?blockif?(msg?==?null)?{//?No?message?indicates?that?the?message?queue?is?quitting.return;}
评论