转载请声明出处:http://blog.csdn.net/qq_24692041/article/details/68066025
Android线程间通讯方式有很多,但是大部分内部实现其实都是handler。今天我们就来看看handler的内部实现机制,实现原理,实现细节。本文主要是为了搞清楚线程间的通讯,Message也可以用于进程间的通讯,在本文中不对此进行详细的讲解,浅尝辄止!后面如果有需要,我会补上Message的进程间通讯相关文章,敬请期待!
本文我们分步骤对Handler消息机制进行分析,这样有条理一点,已更利于阅读。
- 角色分析:
Handler进程间通讯主要关联了Thread,ThreadLocal,Handler,Message,MessageQueue,Looper这几个类。我们先看看这几个类各自在这个实现工程中扮演者什么样的角色!
Thread:整个机制产生的意义,所有这个机制就是为Thread服务!Looper的创建是为Thread而创建,其实是Thread持有。Handler使用的Looper是由Thread提供!
ThreadLocal:Thread属性的存储者,内部维护一个ThreadLocalMap,其中存放了Thread的所有属性,Looper就是存放在这儿。Handler:消息的发起者,发出一个消息。消息的处理者,消息处理的时间到了对该消息进行处理。必须有一个Looper,通过操作Looper持有的MessageQueue实现消息的发送,当Looper通知处理Message的时候,对Message进行处理。
Message:数据和信号携带者,携带数据进行传递。处理时机决定者,通过when属性决定消息的处理时间。消息队列的产生者,将一个个的message对象串联起来,形成消息队列。
MessageQueue:消息存放者,存放了一个消息队列,有消息进来的时候安插在指定的位置,需要处理的时候将消息取出来。消息排队者,将消息按处理的时间进行存放,让消息排队进行处理。
Looper:运行机制全局掌控者,让整个机制活动起来的关键人员,将所有角色联系起来,根据具体实现进行调度,完成整个机制的任务。内部持有一个MessageQueue,
Handler通过关联Looper,联系上MessageQueue。 - 大体的运转结构
了解了这些类在整个任务中充当的角色何彼此之间的联系之后,我们来看看他们大体都做了些什么工作,让整个机制运转起来。
Handler通过sendMessage方法,将Message发送出去,MessageQueue通过queueMessage方法将消息存插入到消息队列中等待被处理。Looper通过loop方法在特定的时间到MessageQueue中将消息取出来,回调Handler的dispatchMessage方法将消息交给Handler处理。 - 具体为什么就将数据在线程之间传递成功了呢?
通过第2点,我们大体了解了整个机制的原理,但是这样做为什么就能实现线程间数据的传递呢?这个问题很关键,在我们源代码分析完了之后再来进行讲解,这儿先不说。 - 源代码剖析:
下面我们对源代码进行剖析,然后再来看看上面提到的理论和问题,整个消息机制就完全理解掌握了!- Handler源码分析:
public class Handler { private static final boolean FIND_POTENTIAL_LEAKS = false; private static final String TAG = "Handler"; //当前handler所在线程的looper final Looper mLooper; //跟looper对应的消息队列 final MessageQueue mQueue; //处理消息的回调 final Callback mCallback; //决定处理消息的方式同步的还是异步的 final boolean mAsynchronous; IMessenger mMessenger; /** * 通过设置这个接口去处理消息,就不需要再定义一个Handler的子类 */ public interface Callback { public boolean handleMessage(Message msg); } /** * Subclasses must implement this to receive messages. * Message和Handler都没有callback才会调用处理消息,这儿啥也没做,留着口给子类去完成了 */ public void handleMessage(Message msg) { } /** * 处理系统消息 * Handle system messages here. */ public void dispatchMessage(Message msg) { //如果msg有回调就交给msg处理 if (msg.callback != null) { handleCallback(msg); } else { //msg没有回调,创建Handler的时候有给回调就交给这个回调处理 if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } //调用自己的handleMessage方法处理,什么也没做,交给子类去具体实现,具体操作。平时我们用的匿名内部类的方式就是走了这一步 handleMessage(msg); } } public Handler() { this(null, false); } /** * 构造方法,设定消息处理回调,如果当前线程中没有Looper的时候,将接不到消息,还会抛出异常 */ public Handler(Callback callback) { this(callback, false); } /** * 构造方法,指定一个Looper,用这个Looper替换默认的Looper */ public Handler(Looper looper) { this(looper, null, false); } public Handler(Looper looper, Callback callback) { this(looper, callback, false); } /** * 设定当前Handler是同步处理消息还是异步处理消息 */ public Handler(boolean async) { this(null, async); } /** * 构造方法,初始化 */ 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()); } } //获取一个Looper,UI线程系统自动调用prepareMainLooper方法,创建了UI线程的looper //如果Handler在子线程中创建,必须先调用prepare创建一个looper,否则myLooper返回的是null,会抛出异常 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; } /** * 构造方法,初始化。跟2个参数的构造方法的区别是,这儿直接给定了looper */ public Handler(Looper looper, Callback callback, boolean async) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async; } /** * 获取trace文件的名字,ANR分析的时候有用 */ public String getTraceName(Message message) { final StringBuilder sb = new StringBuilder(); sb.append(getClass().getName()).append(": "); if (message.callback != null) { sb.append(message.callback.getClass().getName()); } else { sb.append("#").append(message.what); } return sb.toString(); } /** * 获取消息的名称,用消息的callback类名或者what的十六进制命名 * * @param message The message whose name is being queried */ public String getMessageName(Message message) { if (message.callback != null) { //如果规定了message的回调,返回该回调类的名字 return message.callback.getClass().getName(); } //如果message没有指定回调,返回what的十六进制 return "0x" + Integer.toHexString(message.what); } /** * 从消息池中获取一个回收的message对象返回, * 但是这个message的处理handler是调用该方法的handler * 这样效率比直接new一个Message要好 * 如果不想处理消息的handler被指定为调用的handler可以调用Message.obtain方法 */ public final Message obtainMessage() { return Message.obtain(this); } /** * 跟上面的方法差不多,只是多了一点,指定了message的what变量值 */ public final Message obtainMessage(int what) { return Message.obtain(this, what); } public final Message obtainMessage(int what, Object obj) { return Message.obtain(this, what, obj); } public final Message obtainMessage(int what, int arg1, int arg2) { return Message.obtain(this, what, arg1, arg2); } public final Message obtainMessage(int what, int arg1, int arg2, Object obj) { return Message.obtain(this, what, arg1, arg2, obj); } /** * 将一个Runnable放到消息队列中,处理的时候是由当前handler依附的线程处理 */ public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); } /** * 跟上面的方法一样,只是多了一个执行的时间指定,会在(uptimeMillis)这段时间过后才执行 */ public final boolean postAtTime(Runnable r, long uptimeMillis) { return sendMessageAtTime(getPostMessage(r), uptimeMillis); } public final boolean postAtTime(Runnable r, Object token, long uptimeMillis) { return sendMessageAtTime(getPostMessage(r, token), uptimeMillis); } public final boolean postDelayed(Runnable r, long delayMillis) { return sendMessageDelayed(getPostMessage(r), delayMillis); } public final boolean postAtFrontOfQueue(Runnable r) { return sendMessageAtFrontOfQueue(getPostMessage(r)); } public final boolean runWithScissors(final Runnable r, long timeout) { if (r == null) { throw new IllegalArgumentException("runnable must not be null"); } if (timeout < 0) { throw new IllegalArgumentException("timeout must be non-negative"); } if (Looper.myLooper() == mLooper) { r.run(); return true; } BlockingRunnable br = new BlockingRunnable(r); return br.postAndWait(this, timeout); } /** * 移除消息队列中所有待处理的任务 */ public final void removeCallbacks(Runnable r) { mQueue.removeMessages(this, r, null); } /** * Remove any pending posts of Runnable <var>r</var> with Object * <var>token</var> that are in the message queue. If <var>token</var> is null, * all callbacks will be removed. */ public final void removeCallbacks(Runnable r, Object token) { mQueue.removeMessages(this, r, token); } /** * 将消息push到消息队列的队尾,轮到处理该消息的时候会回调handleMessage去处理 * 如果push成功返回true,如果这个消息队列已经exiting,将会push失败,返回false */ public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); } /** * 将一个没有携带数据,只有what值的空消息push到消息队列中 */ public final boolean sendEmptyMessage(int what) { return sendEmptyMessageDelayed(what, 0); } /** * 将一个没有携带数据,只有what值的空消息push到消息队列中,但是会在特定的时间过后才能被delivered */ public final boolean sendEmptyMessageDelayed(int what, long delayMillis) { Message msg = Message.obtain(); msg.what = what; return sendMessageDelayed(msg, delayMillis); } public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) { Message msg = Message.obtain(); msg.what = what; return sendMessageAtTime(msg, uptimeMillis); } /** * 将一个消息放入队列,在当前时间+delayMillis(比如:一个小时之后处理,现在是12点,那就是12:00+1*60*60*1000) * 时间点之前应该要处理的消息全部处理完了之后,会在当前handler依附的线程中处理该消息。 * 这个消息将被传到handleMessage方法中 */ public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); } /** * 将一个消息放入消息队列,在uptimeMillis(比如13:00)这个绝对时间点之前应该处理的消息处理完成之后会处理该消息 */ 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); } /** * 讲一个消息放在队首,这个方法一般不会使用,需要在特定的情况下使用。因为这个方法可能会导致 * 消息队列的排序出现问题,或者一些无法想象的异常出现 */ public final boolean sendMessageAtFrontOfQueue(Message msg) { 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, 0); } /** * 将消息放入队列中,在uptimeMillis(13:00)处理这个消息 * * @param queue 将消息放入这个消息队列 * @param msg 想要处理的消息 * @param uptimeMillis 处理的绝对时间点 * @return */ private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { //指定处理该消息的handler为当前调用的handler msg.target = this; if (mAsynchronous) { //将消息设置为可异步 msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); } /** * 从消息队列中移除指定what值的,未处理的消息.移除之后这些消息对象会被回收,将不会被取出执行 */ public final void removeMessages(int what) { mQueue.removeMessages(this, what, null); } /** * 从消息队列中移除指定what,和obj值,并且未处理的消息,移除之后这些消息对象会被回收,将不会被取出执行 */ public final void removeMessages(int what, Object object) { mQueue.removeMessages(this, what, object); } /** * 从消息队列中移除所有指定obj值,并且未处理的消息和任务,移除之后这些消息对象会被回收,将不会被取出执行 */ public final void removeCallbacksAndMessages(Object token) { mQueue.removeCallbacksAndMessages(this, token); } /** * 查询消息队列中是否有跟指定what值的消息 */ public final boolean hasMessages(int what) { return mQueue.hasMessages(this, what, null); } /** * Check if there are any pending posts of messages with code 'what' and * whose obj is 'object' in the message queue. */ public final boolean hasMessages(int what, Object object) { return mQueue.hasMessages(this, what, object); } /** * 查询消息队列中是否有指定任务 */ public final boolean hasCallbacks(Runnable r) { return mQueue.hasMessages(this, r, null); } // if we can get rid of this method, the handler need not remember its loop // we could instead export a getMessageQueue() method... public final Looper getLooper() { return mLooper; } public final void dump(Printer pw, String prefix) { pw.println(prefix + this + " @ " + SystemClock.uptimeMillis()); if (mLooper == null) { pw.println(prefix + "looper uninitialized"); } else { mLooper.dump(pw, prefix + " "); } } @Override public String toString() { return "Handler (" + getClass().getName() + ") {" + Integer.toHexString(System.identityHashCode(this)) + "}"; } ...... }
- Message源码分析:
public final class Message implements Parcelable { /** * 用于指定当前消息的身份 */ public int what; /** * 该消息所携带的简单数据 */ public int arg1; /** * 消息所携带的简单数据 */ public int arg2; /** * 一个Object类型的数据,这个数据可以用于进程间数据传递,这儿不深究 */ public Object obj; /** * Optional Messenger where replies to this message can be sent. The * semantics of exactly how this is used are up to the sender and * receiver. */ public Messenger replyTo; /** * 通过 {@link Messenger}进行进程间数据传递的时候才会有效,代表发送消息的进程的UID,一般情况下为-1,这儿同样不进行深究; */ public int sendingUid = -1; /** * 用于标志当前消息是否正在使用 */ /*package*/ static final int FLAG_IN_USE = 1 << 0; /** * 用于标志当前消息的同步和异步 */ /*package*/ static final int FLAG_ASYNCHRONOUS = 1 << 1; /** * Flags to clear in the copyFrom method */ /*package*/ static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE; /*package*/ int flags; /*package*/ long when; /*package*/ Bundle data; /** * 处理该消息的handler */ /*package*/ Handler target; /** * 处理消息的回调,如果没有这个回调将会调用Handler的handleMessage方法进行处理 */ /*package*/ Runnable callback; /** * 保存了下一个message对象的地址 */ /*package*/ Message next; private static final Object sPoolSync = new Object(); private static Message sPool; private static int sPoolSize = 0; private static final int MAX_POOL_SIZE = 50; private static boolean gCheckRecycle = true; /** * 从消息池中获取一个message对象返回,避免过多创建对象 */ 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对象返回,避免过多创建对象 * 并且将传进来的消息中的数据复制给message,并返回 */ public static Message obtain(Message orig) { Message m = obtain(); m.what = orig.what; m.arg1 = orig.arg1; m.arg2 = orig.arg2; m.obj = orig.obj; m.replyTo = orig.replyTo; m.sendingUid = orig.sendingUid; if (orig.data != null) { m.data = new Bundle(orig.data); } m.target = orig.target; m.callback = orig.callback; return m; } /** * 从消息池中获取一个message对象返回,避免过多创建对象 * 指定一个handler去处理 */ public static Message obtain(Handler h) { Message m = obtain(); m.target = h; return m; } /** * 从消息池中获取一个message对象返回,避免过多创建对象 * 指定一个handler去处理 * 并指定处理的回调接口 */ public static Message obtain(Handler h, Runnable callback) { Message m = obtain(); m.target = h; m.callback = callback; return m; } /** * Same as {@link #obtain()}, but sets the values for both <em>target</em> and * <em>what</em> members on the Message. * * @param h Value to assign to the <em>target</em> member. * @param what Value to assign to the <em>what</em> member. * @return A Message object from the global pool. */ public static Message obtain(Handler h, int what) { Message m = obtain(); m.target = h; m.what = what; return m; } /** * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, and <em>obj</em> * members. * * @param h The <em>target</em> value to set. * @param what The <em>what</em> value to set. * @param obj The <em>object</em> method to set. * @return A Message object from the global pool. */ public static Message obtain(Handler h, int what, Object obj) { Message m = obtain(); m.target = h; m.what = what; m.obj = obj; return m; } /** * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, * <em>arg1</em>, and <em>arg2</em> members. * * @param h The <em>target</em> value to set. * @param what The <em>what</em> value to set. * @param arg1 The <em>arg1</em> value to set. * @param arg2 The <em>arg2</em> value to set. * @return A Message object from the global pool. */ public static Message obtain(Handler h, int what, int arg1, int arg2) { Message m = obtain(); m.target = h; m.what = what; m.arg1 = arg1; m.arg2 = arg2; return m; } /** * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, * <em>arg1</em>, <em>arg2</em>, and <em>obj</em> members. * * @param h The <em>target</em> value to set. * @param what The <em>what</em> value to set. * @param arg1 The <em>arg1</em> value to set. * @param arg2 The <em>arg2</em> value to set. * @param obj The <em>obj</em> value to set. * @return A Message object from the global pool. */ public static Message obtain(Handler h, int what, int arg1, int arg2, Object obj) { Message m = obtain(); m.target = h; m.what = what; m.arg1 = arg1; m.arg2 = arg2; m.obj = obj; return m; } /** * @hide */ public static void updateCheckRecycle(int targetSdkVersion) { if (targetSdkVersion < Build.VERSION_CODES.LOLLIPOP) { gCheckRecycle = false; } } /** * 回收message,先检查当前消息是否正在使用,如果正在使用抛出异常 * 如果没有使用就会回收掉,回收之后将不能再使用这个消息 */ public void recycle() { if (isInUse()) { if (gCheckRecycle) { throw new IllegalStateException("This message cannot be recycled because it " + "is still in use."); } return; } recycleUnchecked(); } /** * 内部调用回收message,不会检查当前消息是否正在使用,直接回收,回收之后将不能再使用这个消息 */ 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++; } } } /** * 复制o的数据(不包括队列相关的数据)给当前消息 */ public void copyFrom(Message o) { this.flags = o.flags & ~FLAGS_TO_CLEAR_ON_COPY_FROM; this.what = o.what; this.arg1 = o.arg1; this.arg2 = o.arg2; this.obj = o.obj; this.replyTo = o.replyTo; this.sendingUid = o.sendingUid; if (o.data != null) { this.data = (Bundle) o.data.clone(); } else { this.data = null; } } /** * 返回消息的处理时间 */ public long getWhen() { return when; } /* *指定处理该消息的handler */ public void setTarget(Handler target) { this.target = target; } /** * 获取将处理该消息的handler */ public Handler getTarget() { return target; } /** * 处理消息的回调,如果没有设置这个回调,调用handler的handleMessage方法进行处理 */ public Runnable getCallback() { return callback; } /** * 获取Bundle类型的data数据,这个数据是通过setData方法传递进来的 * 其实这个方法中的数据可用于进程间数据传递,这儿我们不深究 * * @see #peekData() * @see #setData(Bundle) */ public Bundle getData() { if (data == null) { data = new Bundle(); } return data; } /** * 跟setData差不多,但是不同的是返回的data可能为null */ public Bundle peekData() { return data; } /** * 给data赋值 */ public void setData(Bundle data) { this.data = data; } /** * 发送一个消息给处理该消息的handler,如果这个handler为null,将会抛出空指针异常 */ public void sendToTarget() { target.sendMessage(this); } /** * 如果返回true,该消息就是异步的,将不会手looper的限制。 * 一般来说我们的消息是受looper的控制是同步的 */ public boolean isAsynchronous() { return (flags & FLAG_ASYNCHRONOUS) != 0; } /** * 对消息的异步进行设置,如果设置为true,消息不会受looper限制,将会是异步的 */ public void setAsynchronous(boolean async) { if (async) { flags |= FLAG_ASYNCHRONOUS; } else { flags &= ~FLAG_ASYNCHRONOUS; } } /** * 当前消息是否正在使用 */ boolean isInUse() { return ((flags & FLAG_IN_USE) == FLAG_IN_USE); } /*package*/ void markInUse() { flags |= FLAG_IN_USE; } /** * 构造器,一般来说不要直接通过构造器创建message,尽量用obtain方法 */ public Message() { }
- MessageQueue源代码分析:
* 内部维护消息队列,这个消息队列中的消息是按照处理的时间先后顺序排队的 * 跟looper协作进行消息的分发,指派。 * 消息是通过Handler关联上Looper之后,放到消息队列中,然 * 后通过looper取出调用handler的dispatchMessage方法进行处理 */ public final class MessageQueue { private static final String TAG = "MessageQueue"; private static final boolean DEBUG = false; // 代表当前消息队列能否exit private final boolean mQuitAllowed; @SuppressWarnings("unused") private long mPtr; // used by native code Message mMessages; private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>(); private SparseArray<FileDescriptorRecord> mFileDescriptorRecords; private IdleHandler[] mPendingIdleHandlers; // private boolean enqueueMessage; // Indicates whether next() is blocked waiting in pollOnce() with a non-zero timeout. private boolean mBlocked; // The next barrier token. // Barriers are indicated by messages with a null target whose arg1 field carries the token. private int mNextBarrierToken; private native static long nativeInit(); private native static void nativeDestroy(long ptr); private native void nativePollOnce(long ptr, int timeoutMillis); /*non-static for callbacks*/ private native static void nativeWake(long ptr); private native static boolean nativeIsPolling(long ptr); private native static void nativeSetFileDescriptorEvents(long ptr, int fd, int events); //构造方法,初始化 MessageQueue(boolean quitAllowed) { mQuitAllowed = quitAllowed; mPtr = nativeInit(); } @Override protected void finalize() throws Throwable { try { dispose(); } finally { super.finalize(); } } // Disposes of the underlying message queue. // Must only be called on the looper thread or the finalizer. private void dispose() { if (mPtr != 0) { nativeDestroy(mPtr); mPtr = 0; } } /** * 判断跟这个消息队列关联的looper是不是为空闲状态,true表示空闲,false表示非空闲 */ public boolean isIdle() { synchronized (this) { //获取系统时间 final long now = SystemClock.uptimeMillis(); //如果消息队列中没有消息,或者需要处理的消息里面时间最早的一个都是在当前系统时间的后面,那就代表着空闲 return mMessages == null || now < mMessages.when; } } public void addIdleHandler(@NonNull IdleHandler handler) { if (handler == null) { throw new NullPointerException("Can't add a null IdleHandler"); } synchronized (this) { mIdleHandlers.add(handler); } } public void removeIdleHandler(@NonNull IdleHandler handler) { synchronized (this) { mIdleHandlers.remove(handler); } } public boolean isPolling() { synchronized (this) { return isPollingLocked(); } } private boolean isPollingLocked() { // If the loop is quitting then it must not be idling. // We can assume mPtr != 0 when mQuitting is false. return !mQuitting && nativeIsPolling(mPtr); } public void addOnFileDescriptorEventListener(@NonNull FileDescriptor fd, @OnFileDescriptorEventListener.Events int events, @NonNull OnFileDescriptorEventListener listener) { if (fd == null) { throw new IllegalArgumentException("fd must not be null"); } if (listener == null) { throw new IllegalArgumentException("listener must not be null"); } synchronized (this) { updateOnFileDescriptorEventListenerLocked(fd, events, listener); } } public void removeOnFileDescriptorEventListener(@NonNull FileDescriptor fd) { if (fd == null) { throw new IllegalArgumentException("fd must not be null"); } synchronized (this) { updateOnFileDescriptorEventListenerLocked(fd, 0, null); } } private void updateOnFileDescriptorEventListenerLocked(FileDescriptor fd, int events, OnFileDescriptorEventListener listener) { final int fdNum = fd.getInt$(); int index = -1; FileDescriptorRecord record = null; if (mFileDescriptorRecords != null) { index = mFileDescriptorRecords.indexOfKey(fdNum); if (index >= 0) { record = mFileDescriptorRecords.valueAt(index); if (record != null && record.mEvents == events) { return; } } } if (events != 0) { events |= OnFileDescriptorEventListener.EVENT_ERROR; if (record == null) { if (mFileDescriptorRecords == null) { mFileDescriptorRecords = new SparseArray<FileDescriptorRecord>(); } record = new FileDescriptorRecord(fd, events, listener); mFileDescriptorRecords.put(fdNum, record); } else { record.mListener = listener; record.mEvents = events; record.mSeq += 1; } nativeSetFileDescriptorEvents(mPtr, fdNum, events); } else if (record != null) { record.mEvents = 0; mFileDescriptorRecords.removeAt(index); } } // Called from native code. private int dispatchEvents(int fd, int events) { // Get the file descriptor record and any state that might change. final FileDescriptorRecord record; final int oldWatchedEvents; final OnFileDescriptorEventListener listener; final int seq; synchronized (this) { record = mFileDescriptorRecords.get(fd); if (record == null) { return 0; // spurious, no listener registered } oldWatchedEvents = record.mEvents; events &= oldWatchedEvents; // filter events based on current watched set if (events == 0) { return oldWatchedEvents; // spurious, watched events changed } listener = record.mListener; seq = record.mSeq; } // Invoke the listener outside of the lock. int newWatchedEvents = listener.onFileDescriptorEvents( record.mDescriptor, events); if (newWatchedEvents != 0) { newWatchedEvents |= OnFileDescriptorEventListener.EVENT_ERROR; } // Update the file descriptor record if the listener changed the set of // events to watch and the listener itself hasn't been updated since. if (newWatchedEvents != oldWatchedEvents) { synchronized (this) { int index = mFileDescriptorRecords.indexOfKey(fd); if (index >= 0 && mFileDescriptorRecords.valueAt(index) == record && record.mSeq == seq) { record.mEvents = newWatchedEvents; if (newWatchedEvents == 0) { mFileDescriptorRecords.removeAt(index); } } } } // Return the new set of events to watch for native code to take care of. return newWatchedEvents; } /** * 如果消息队列中还有下一个消息,取出这个消息 * * @return */ 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) { // 跳过消息队列中的异步消息 do { prevMsg = msg; msg = msg.next; } while (msg != null && !msg.isAsynchronous()); } if (msg != null) { if (now < msg.when) { // 如果第一个消息的处理时间还没到,就设定一个闹钟,等到闹钟响起,再开始处理 nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE); } else { //获取一个消息对象 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 { // 消息对立中没有消息 nextPollTimeoutMillis = -1; } // 所有的消息都处理完之后,退出message 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; } } /** * 退出消息队列,在looper退出的时候调用 * * @param safe true表示安全退出,false强行退出 */ 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); } } public int postSyncBarrier() { return postSyncBarrier(SystemClock.uptimeMillis()); } private int postSyncBarrier(long when) { // Enqueue a new sync barrier token. // We don't need to wake the queue because the purpose of a barrier is to stall it. synchronized (this) { final int token = mNextBarrierToken++; final Message msg = Message.obtain(); msg.markInUse(); msg.when = when; msg.arg1 = token; Message prev = null; Message p = mMessages; if (when != 0) { while (p != null && p.when <= when) { prev = p; p = p.next; } } if (prev != null) { // invariant: p == prev.next msg.next = p; prev.next = msg; } else { msg.next = p; mMessages = msg; } return token; } } public void removeSyncBarrier(int token) { // Remove a sync barrier token from the queue. // If the queue is no longer stalled by a barrier then wake it. synchronized (this) { Message prev = null; Message p = mMessages; while (p != null && (p.target != null || p.arg1 != token)) { prev = p; p = p.next; } if (p == null) { throw new IllegalStateException("The specified message queue synchronization " + " barrier token has not been posted or has already been removed."); } final boolean needWake; if (prev != null) { prev.next = p.next; needWake = false; } else { mMessages = p.next; needWake = mMessages == null || mMessages.target != null; } p.recycleUnchecked(); // If the loop is quitting then it is already awake. // We can assume mPtr != 0 when mQuitting is false. if (needWake && !mQuitting) { nativeWake(mPtr); } } } 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(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) { //消息队列中还没有消息存在或者当前插入消息的处理时间比队列中存在 // 的所有消息的处理时间都要早,就将该消息放在队首 msg.next = p; mMessages = msg; needWake = mBlocked; } else { /** * 将消息存放到队列的中间位置,根据处理的时机,跟队列中所有消息的处理时间进行比较,按从早到迟的顺序安插 */ 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; } /** * 查询handler相关联的消息队列中,是否有指定what和指定obj的消息 * * @param h 想要查询的关联handler * @param what 消息的what值 * @param object 消息的obj值 * @return */ boolean hasMessages(Handler h, int what, Object object) { if (h == null) { return false; } synchronized (this) { Message p = mMessages; while (p != null) { if (p.target == h && p.what == what && (object == null || p.obj == object)) { return true; } p = p.next; } return false; } } /** * 查询handler相关联的消息队列中,是否有指定obj的任务 * * @param h 想要查询的关联handler * @param object 任务的obj值 * @return */ boolean hasMessages(Handler h, Runnable r, Object object) { if (h == null) { return false; } synchronized (this) { Message p = mMessages; while (p != null) { if (p.target == h && p.callback == r && (object == null || p.obj == object)) { return true; } p = p.next; } return false; } } /** * 移除跟h相关联的消息队列中,指定what值和obj值的消息 * * @param h * @param what * @param object */ void removeMessages(Handler h, int what, Object object) { if (h == null) { return; } synchronized (this) { Message p = mMessages; // Remove all messages at front. while (p != null && p.target == h && p.what == what && (object == null || p.obj == object)) { Message n = p.next; mMessages = n; p.recycleUnchecked(); p = n; } // Remove all messages after front. while (p != null) { Message n = p.next; if (n != null) { if (n.target == h && n.what == what && (object == null || n.obj == object)) { Message nn = n.next; n.recycleUnchecked(); p.next = nn; continue; } } p = n; } } } /** * 移除跟h相关联的消息队列中,指定obj值的任务 * * @param h * @param r * @param object */ void removeMessages(Handler h, Runnable r, Object object) { if (h == null || r == null) { return; } synchronized (this) { Message p = mMessages; // Remove all messages at front. while (p != null && p.target == h && p.callback == r && (object == null || p.obj == object)) { Message n = p.next; mMessages = n; p.recycleUnchecked(); p = n; } // Remove all messages after front. while (p != null) { Message n = p.next; if (n != null) { if (n.target == h && n.callback == r && (object == null || n.obj == object)) { Message nn = n.next; n.recycleUnchecked(); p.next = nn; continue; } } p = n; } } } /** * 移除跟指定handler相关联的消息队列中,指定obj值的所有消息 * * @param h * @param object */ void removeCallbacksAndMessages(Handler h, Object object) { if (h == null) { return; } synchronized (this) { Message p = mMessages; // Remove all messages at front. while (p != null && p.target == h && (object == null || p.obj == object)) { Message n = p.next; mMessages = n; p.recycleUnchecked(); p = n; } // Remove all messages after front. while (p != null) { Message n = p.next; if (n != null) { if (n.target == h && (object == null || n.obj == object)) { Message nn = n.next; n.recycleUnchecked(); p.next = nn; continue; } } p = n; } } } //回收消息队列中所有的消息 private void removeAllMessagesLocked() { Message p = mMessages; while (p != null) { Message n = p.next; p.recycleUnchecked(); p = n; } mMessages = null; } /** * 安全退出消息队列 */ private void removeAllFutureMessagesLocked() { final long now = SystemClock.uptimeMillis(); Message p = mMessages; if (p != null) { if (p.when > now) { //如果在消息设定的处理时间还没到,直接回收掉,将不会处理 removeAllMessagesLocked(); } else { Message n; for (; ; ) { n = p.next; if (n == null) { return; } if (n.when > now) { break; } p = n; } p.next = null; do { p = n; n = p.next; p.recycleUnchecked(); } while (n != null); } } } void dump(Printer pw, String prefix) { synchronized (this) { long now = SystemClock.uptimeMillis(); int n = 0; for (Message msg = mMessages; msg != null; msg = msg.next) { pw.println(prefix + "Message " + n + ": " + msg.toString(now)); n++; } pw.println(prefix + "(Total messages: " + n + ", polling=" + isPollingLocked() + ", quitting=" + mQuitting + ")"); } } ...... }
- Looper源代码分析:
public final class Looper { private static final String TAG = "Looper"; /* ThreadLocal保存了线程所有的变量,可以通过get方法去获取对应的变量,取得的变量是什么取决于泛型, 这儿传的是Looper,所以获取的是线程的Looper变量,在prepare方法中会创建一个looper存在sThreadLocal中, 如果没有先prepare,sThreadLocal.get取得的就是null*/ static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); private static Looper sMainLooper; // guarded by Looper.class final MessageQueue mQueue; final Thread mThread; private Printer mLogging; private long mTraceTag; /** * 初始化一个looper给当前线程 */ public static void prepare() { prepare(true); } private static void prepare(boolean quitAllowed) { //先查询sThreadLocal,如果已经存在looper会抛出异常 if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } //创建一个looper对象存放到sThreadLocal中 sThreadLocal.set(new Looper(quitAllowed)); } /** * 为UI线程准备的,系统初始化UI线程的时候调用。我们一般不需要调用这个方法 */ public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); } } /** * 获取UI线程中的looper变量 */ public static Looper getMainLooper() { synchronized (Looper.class) { return sMainLooper; } } /** * 从MessageQueue中取出Message,调用Handler中的dispatchMessage,对消息进行处理 */ public static void loop() { //获取到looper,如果没有之前prepare,取到的会是null,抛出异常 final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } //取出消息中的消息队里MessageQueue 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. /** * 确认当前线程的身份是属于当前本地进程,确保track是属于这个线程 */ 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.isTagEnabled(traceTag)) { //开始记录trace,在ANR分析中会用到trace.txt文件 Trace.traceBegin(traceTag, msg.target.getTraceName(msg)); } try { //调用handler的方法处理消息 msg.target.dispatchMessage(msg); } finally { if (traceTag != 0) { //结束trace记录 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(); } } /** * R获取当前线程的looper变量 */ public static @Nullable Looper myLooper() { return sThreadLocal.get(); } /** * Return the {@link MessageQueue} object associated with the current * thread. This must be called from a thread running a Looper, or a * NullPointerException will be thrown. */ public static @NonNull MessageQueue myQueue() { return myLooper().mQueue; } /** * 构造方法私有化,在prepare中调用,初始化。 * * @param quitAllowed */ private Looper(boolean quitAllowed) { //创建一个消息队列,用于存放消息 mQueue = new MessageQueue(quitAllowed); //取得当前线程,让该looper跟当前线程关联 mThread = Thread.currentThread(); } /** * 判断looper是否为当前线程的looper */ public boolean isCurrentThread() { return Thread.currentThread() == mThread; } /** * 记录被该looper对象处理的所有消息的控制标志,如果enabled, * 将会通过Trace.traceBegin和Trace.traceEnd(traceTag)控制记录每一条消息的处理状况; * * @param printer A Printer object that will receive log messages, or * null to disable message logging. */ public void setMessageLogging(@Nullable Printer printer) { mLogging = printer; } /** * {@hide} */ public void setTraceTag(long traceTag) { mTraceTag = traceTag; } /** * 退出当前looper操作 * 在当前looper的消息队列没有消息需要处理的时候才可以调用该方法, * 该方法调用的时候会将所有消息队列中的消息回收, * 在这个方法之后所有的消息将不会再被处理,包括当前正在处理的消息 * 一般来说用quitSafely代替该方法,因为该方法不安全,他不能保证已经被delivered的消息处理完成 */ public void quit() { mQueue.quit(false); } /** * 安全终止looper * 会先将消息的处理时间在当前时间点之前的消息全部处理完之后才会终止looper, * 但是不能保证执行时间是在当前时间之后的消息被处理 */ public void quitSafely() { mQueue.quit(true); } /** * 获取当前looper关联的线程 */ public @NonNull Thread getThread() { return mThread; } /** * 获取当前looper持有的消息队列 */ public @NonNull MessageQueue getQueue() { return mQueue; } public void dump(@NonNull Printer pw, @NonNull String prefix) { pw.println(prefix + toString()); mQueue.dump(pw, prefix + " "); } @Override public String toString() { return "Looper (" + mThread.getName() + ", tid " + mThread.getId() + ") {" + Integer.toHexString(System.identityHashCode(this)) + "}"; } }
- Handler源码分析:
- 知识点串联,细节分析
上面将主要的三个类Handler,Message,MessageQueue的源代码进行了初步的分析,现在我们将几个重要的方法取出来,具体的分析。将整个机制是怎么运转起来的弄明白!- Looper和MessageQueue,Thread的关系
我们从Handler入手,先看看Handler构造方法:
当我们创建Handler的时候,最终调用的都是这两个构造方法的其中之一。一般情况下,我们是调用到了第一个构造方法。可以看到,在这两个构造方法中对Handler的四个变量mLooper,mQueue,mCallback,mAsynchronous进行初始化,我们对两个特殊的变量mLooper和mQueue进行分析,mLooper是通过Looper.myLooper获取的,mQueue也是通过looper获取的。我们先具体的分析几个方法,然后来捋一捋这里面的关系。/** * 构造方法,初始化 */ 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()); } } //获取一个Looper,UI线程系统自动调用prepareMainLooper方法,创建了UI线程的looper //如果Handler在子线程中创建,必须先调用prepare创建一个looper,否则myLooper返回的是null,会抛出异常 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; } /** * 构造方法,初始化。跟2个参数的构造方法的区别是,这儿直接给定了looper */ public Handler(Looper looper, Callback callback, boolean async) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async; }
先看一段代码Looper的构造方法/** * 构造方法私有化,在prepare中调用,初始化。 * * @param quitAllowed */ private Looper(boolean quitAllowed) { //创建一个消息队列,用于存放消息 mQueue = new MessageQueue(quitAllowed); //取得当前线程,让该looper跟当前线程关联 mThread = Thread.currentThread(); }
看上面的这段代码,这是Looper类的构造方法,这个方法是private修饰的,也就是说不能在其他类中通过new关键字来创建一个Looper的实例,需要通过prepare方法进行创建,我们再来看看prepare方法的具体实现。/** * 初始化一个looper给当前线程 */ public static void prepare() { prepare(true); } private static void prepare(boolean quitAllowed) { //先查询sThreadLocal,如果已经存在looper会抛出异常 if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } //创建一个looper对象存放到sThreadLocal中 sThreadLocal.set(new Looper(quitAllowed)); }
注意看上面的代码,这儿prepare的时候调用了一个内部private修饰的prepare方法,这儿引入了一个变量sThreadLocal。一会儿我们具体说这个变量,先看看sThreadLocal.set(newLooper(quitAllowed));这句代码是调用构造方法创建了一个Looper实例,并且交给了ThreadLocal保存。这儿我想要说明白的一个点,那就是Looper的创建过程,是通过prepare方法调用构造方法进行初始化的,在初始化的时候,创建了一个MessageQueue实例mQueue,并且获取到了当前线程的实例mThread。通过初始化,让Looper跟当前线程绑定上了,并且还绑定了一个消息队列
- Handler和Looper,MessageQueue,Thread的关系
现在清楚了Looper跟Thread还有MessageQueue的关系。我们再来看看Handler跟Looper,Thread,MessageQueue的关系。上面Handler的构造方法初始化的代码中很明显,通过Looper.myLooper方法得到了Looper的实例。现在来看看myLooper的具体实现。/** * 获取当前线程的looper变量 */ public static @Nullable Looper myLooper() { return sThreadLocal.get(); }
myLooper方法中,是通过sThreadLocal这个变量get出来的。ThreadLocal又是什么鬼东西?别急,我们先来看看ThreadLocal的get方法,然后我再进行讲解。public T get() { //获取当前线程的实例 Thread t = Thread.currentThread(); //得到Thread中的ThreadLocalMap实例 ThreadLocalMap map = getMap(t); //遍历Map集合,将Value值返回 if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) //泛型,根据初始化的时候指定的类型返回当前线程的特定变量 return (T)e.value; } //如果集合为null,先创建一个null值代替返回 return setInitialValue(); }
ThreadLocal用于存放Thread线程的变量,内部维护了一个内部类ThreadLocalMap类似于HashMap,以键值对的形式将线程所有的属性都存起来。所以Looper在创建的时候也会保存在ThreadLocal中。在那个线程中创建,他就属于那个线程!在Looper的构造方法中有这么一段代码sThreadLocal.set(newLooper(quitAllowed));其实这儿就是将新创建出来的Looper实例保存到了当前线程的ThreadLocal中。
好了,搞清楚ThreadLocal了,那myPrepare方法的实现就不难看懂了吧!其实就是获取当前线程的Looper实例,因为前面我们说了Looper跟MessageQueue和Thread是关联起来的。所以Handler就能通过looper实例去操作Thread,和MessageQueue了。
- Handler和Message,MessageQueue的关系
上面Handler,Looper,MessageQueue,Thread之间的关系已经捋清楚了,现在我们再来看看Handler和Message,MessageQueue,Looper之间的关系
再把这儿捋通,整个Handler消息机制的就活络起来了,就差中间的一些细节了。
我们一般使用Handler,都是创建一个对象,然后通过Handler的sendMessage,或者sendEmptyMessage或者SendMessageDelay等等方法,将消息发送出去,然后通过回调或者HandlerMessage方法对消息进行处理。
我们来看看下面这几个Handler类中发送消息的方法:/** * 将消息push到消息队列的队尾,轮到处理该消息的时候会回调handleMessage去处理 * 如果push成功返回true,如果这个消息队列已经exiting,将会push失败,返回false */ public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); } /** * 将一个没有携带数据,只有what值的空消息push到消息队列中 */ public final boolean sendEmptyMessage(int what) { return sendEmptyMessageDelayed(what, 0); } /** * 将一个没有携带数据,只有what值的空消息push到消息队列中,但是会在特定的时间过后才能被delivered */ public final boolean sendEmptyMessageDelayed(int what, long delayMillis) { Message msg = Message.obtain(); msg.what = what; return sendMessageDelayed(msg, delayMillis); } public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) { Message msg = Message.obtain(); msg.what = what; return sendMessageAtTime(msg, uptimeMillis); } /** * 将一个消息放入队列,在当前时间+delayMillis(比如:一个小时之后处理,现在是12点,那就是12:00+1*60*60*1000) * 时间点之前应该要处理的消息全部处理完了之后,会在当前handler依附的线程中处理该消息。 * 这个消息将被传到handleMessage方法中 */ public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); } /** * 将一个消息放入消息队列,在uptimeMillis(比如13:00)这个绝对时间点之前应该处理的消息处理完成之后会处理该消息 */ 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方法,也就是说最后起作用的还是enqueueMessage方法。直接将enqueueMessage方法的实现代码拿出来,具体看一看!/** * 将消息放入队列中,在uptimeMillis(13:00)处理这个消息 * * @param queue 将消息放入这个消息队列 * @param msg 想要处理的消息 * @param uptimeMillis 处理的绝对时间点 * @return */ private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { //指定处理该消息的handler为当前调用的handler msg.target = this; if (mAsynchronous) { //将消息设置为可异步 msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
很明显最后是调用了MessageQuenue中的enqueueMessage方法,这儿的MessageQuenue就是通过Looper获取到的,一定要时刻记住这一点!同样的将MessageQueue中的enqueueMessage方法的实现拿出来看看。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(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) { //消息队列中还没有消息存在或者当前插入消息的处理时间比队列中存在 // 的所有消息的处理时间都要早,就将该消息放在队首 msg.next = p; mMessages = msg; needWake = mBlocked; } else { /** * 将消息存放到队列的中间位置,根据处理的时机,跟队列中所有消息的处理时间进行比较,按从早到迟的顺序安插 */ 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放入到消息队列中的一个操作,很简单。但是,其中有很多细节的东西,我们来说一说。这儿引入了一个数据结构队列。其实队列跟单链表差不多,之间有一定的差别。但是,如果对单链表掌握的不错的同学,理解起队列也不难!之前我有一篇关于单链表的博文《数据结构之Java单链表反转》一文中对单链表讲解得已经很详细。如果对队列理解不到位,可以去看看之后再回过头来看这篇博文。不然会很费劲。在这儿,就不多说了。
回到正题, 整个消息机制,其实就是包含了两个部分:
- 将消息放入消息队列中存放起来,等待处理
- 在特定的时机将消息取出进行处理(这个部分包含了消息的回收)
现在Message已经成功存放到MessageQueue中了,第一部分算是完成了,整个机制算是完成一半!接下来就要去搞清楚第二部分的东西,这些消息是什么时候被处理的呢?又是谁去处理,谁去分发?在这个处理的过程中上面提到的几个类分别都扮演什么角色呢?
我们在子线程中使用Handler的过程是先prepare,然后将消息发送出去,最后调用loop方法。这儿调用prepare方法前面已经讲解过了,是为当前线程创建Looper实例,并且初始化。现在我们再来看看loop方法的实现。/** * 从MessageQueue中取出Message,调用Handler中的dispatchMessage,对消息进行处理 */ public static void loop() { //获取到looper,如果没有之前prepare,取到的会是null,抛出异常 final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } //取出消息中的消息队里MessageQueue 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. /** * 确认当前线程的身份是属于当前本地进程,确保track是属于这个线程 */ 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.isTagEnabled(traceTag)) { //开始记录trace,在ANR分析中会用到trace.txt文件 Trace.traceBegin(traceTag, msg.target.getTraceName(msg)); } try { //调用handler的方法处理消息 msg.target.dispatchMessage(msg); } finally { if (traceTag != 0) { //结束trace记录 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(); } }
上面的代码很简单,其实就是调用MessageQueue中的next方法取出消息,取到之后调用handler的dispatchMessage方法对消息进行分发。需要注意的是:在取消息的时候有可能会阻塞,在调用dispatchMessage分发之前会记录trace,分发完成之后会结束Trac记录,ANR的出现有可能出现在这个地方,我们分析ANR的时候就是通过这儿生成的trace文件进行分析。
下面我们来看看MessageQueue中next方法的具体代码实现。/** * 如果消息队列中还有下一个消息,根据消息处理的时机取出这个消息 * * @return */ 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消息机制通知系统执行一条延迟的命令 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) { // 跳过消息队列中的异步消息 do { prevMsg = msg; msg = msg.next; } while (msg != null && !msg.isAsynchronous()); } if (msg != null) { if (now < msg.when) { // 计算下一次循环的时机,如果消息处理的时间是现在,计算出来的结果就是0,就不会阻塞 nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE); } else { //获取一个消息对象 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 { // 消息对立中没有消息,将下一次执行循环的时间定为-1,进入阻塞状态 nextPollTimeoutMillis = -1; } // 所有的消息都处理完之后,退出message 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; } }
上面的代码很清楚了,取出消息是一个可能阻塞的过程,因为有可能现在去取的这个消息需要处理的时机是几分钟或者几秒钟之后,所以这儿会定一个闹钟,然后通知系统做一个延时。这儿大体是这个意思,我们就不深究了哈!
然后在看看Handler中dispatchMessage方法的具体实现/** * 处理系统消息 * Handle system messages here. */ public void dispatchMessage(Message msg) { //如果msg有回调就交给msg处理 if (msg.callback != null) { handleCallback(msg); } else { //msg没有回调,创建Handler的时候有给回调就交给这个回调处理 if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } //调用自己的handleMessage方法处理,什么也没做,交给子类去具体实现,具体操作。平时我们用的匿名内部类的方式就是走了这一步 handleMessage(msg); } }
很明显,当Handler收到处理消息的信号的时候,会先看Message有没有callback回调,有就交给他处理,没有就看看自己有没有callback回调,同样的有,就交给callback回调处理,没有就调用handleMessage方法。在Handler中handleMessage方法什么也没做,所以我们平时简单的做法就是用一个匿名内部类对消息处理。这种方式不推荐,因为callback的存在就是为了考虑性能的问题,为了避免Handler的子类出现。
到这儿,整个Handler消息机制中的相关类,分别充当的角色,还有彼此之间的联系就分析完了。
- Looper和MessageQueue,Thread的关系