/** * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.os; import android.util.Log; import android.util.Printer; //引入这样一个类的作用 import java.lang.reflect.Modifier; public class Handler { /** * Set this flag to true to detect anonymous, local or member classes * that extend this Handler class and that are not static. These kind * of classes can potentially create leaks. */ private static final boolean FIND_POTENTIAL_LEAKS = false; private static final String TAG = "Handler"; /*** * 学习内部接口的使用方法及优势 * Callback interface you can use when instantiating a Handler to avoid * having to implement your own subclass of Handler. */ //定义一个处理消息的内部接口,马蛋,接口真多,何时调用,返回值也很重要 public interface Callback { public boolean handleMessage(Message msg); } /*** * Subclasses must implement this to receive messages. */ //子类需要实现该方法以处理消息,我们的自由 public void handleMessage(Message msg) { } //一般不会主动调用吧 public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { //设置了callback时的处理方法 if (mCallback != null) { //接口是否实现,该callback必须含有handlemessage方法,看返回值 if (mCallback.handleMessage(msg)) { return; } } //最后调用本身的handlemessage handleMessage(msg); } } /*** * Default constructor associates this handler with the queue for the * current thread. * * If there isn't one, this handler won't be able to receive messages. */ //默认构造函数,和当前线程的消息队列绑定,如果当前线程没有looper,则不能创建handler public Handler() { if (FIND_POTENTIAL_LEAKS) { //这用到了反射 final Class 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 mLooper = Looper.myLooper(); if (mLooper == null) { //创建handler的前提是该线程拥有looper throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } //获取当前消息队列 mQueue = mLooper.mQueue; mCallback = null; } /*** * Constructor associates this handler with the queue for the * current thread and takes a callback interface in which you can handle * messages. */ //加入回调 public Handler(Callback callback) { if (FIND_POTENTIAL_LEAKS) { final Class 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; } /*** * Use the provided queue instead of the default one. */ //不使用默认的looper public Handler(Looper looper) { mLooper = looper; mQueue = looper.mQueue; mCallback = null; } /*** * Use the provided queue instead of the default one and take a callback * interface in which to handle messages. */ public Handler(Looper looper, Callback callback) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; } /*** * Returns a string representing the name of the specified message. * The default implementation will either return the class name of the * message callback if any, or the hexadecimal representation of the * message "what" field. * * @param message The message whose name is being queried */ //获取消息的名字,message.callback? public String getMessageName(Message message) { if (message.callback != null) { return message.callback.getClass().getName(); } return "0x" + Integer.toHexString(message.what); } /*** * Returns a new {@link android.os.Message Message} from the global message pool. More efficient than * creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this). * If you don't want that facility, just call Message.obtain() instead. */ //直接调用message的方法,传入handler的意义 public final Message obtainMessage() { return Message.obtain(this); } /*** * Same as {@link #obtainMessage()}, except that it also sets the what member of the returned Message. * * @param what Value to assign to the returned Message.what field. * @return A Message from the global message pool. */ public final Message obtainMessage(int what) { return Message.obtain(this, what); } /*** * * Same as {@link #obtainMessage()}, except that it also sets the what and obj members * of the returned Message. * * @param what Value to assign to the returned Message.what field. * @param obj Value to assign to the returned Message.obj field. * @return A Message from the global message pool. */ public final Message obtainMessage(int what, Object obj) { return Message.obtain(this, what, obj); } /*** * * Same as {@link #obtainMessage()}, except that it also sets the what, arg1 and arg2 members of the returned * Message. * @param what Value to assign to the returned Message.what field. * @param arg1 Value to assign to the returned Message.arg1 field. * @param arg2 Value to assign to the returned Message.arg2 field. * @return A Message from the global message pool. */ public final Message obtainMessage(int what, int arg1, int arg2) { return Message.obtain(this, what, arg1, arg2); } /*** * * Same as {@link #obtainMessage()}, except that it also sets the what, obj, arg1,and arg2 values on the * returned Message. * @param what Value to assign to the returned Message.what field. * @param arg1 Value to assign to the returned Message.arg1 field. * @param arg2 Value to assign to the returned Message.arg2 field. * @param obj Value to assign to the returned Message.obj field. * @return A Message from the global message pool. */ public final Message obtainMessage(int what, int arg1, int arg2, Object obj) { return Message.obtain(this, what, arg1, arg2, obj); } /*** * Causes the Runnable r to be added to the message queue. * The runnable will be run on the thread to which this handler is * attached. * * @param r The Runnable that will be executed. * * @return Returns true if the Runnable was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. */ //将runnable对象添加到消息队列 public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); } /*** * Causes the Runnable r to be added to the message queue, to be run * at a specific time given by uptimeMillis. * The time-base is {@link android.os.SystemClock#uptimeMillis}. * The runnable will be run on the thread to which this handler is attached. * * @param r The Runnable that will be executed. * @param uptimeMillis The absolute time at which the callback should run, * using the {@link android.os.SystemClock#uptimeMillis} time-base. * * @return Returns true if the Runnable was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. Note that a * result of true does not mean the Runnable will be processed -- if * the looper is quit before the delivery time of the message * occurs then the message will be dropped. */ public final boolean postAtTime(Runnable r, long uptimeMillis) { return sendMessageAtTime(getPostMessage(r), uptimeMillis); } /*** * Causes the Runnable r to be added to the message queue, to be run * at a specific time given by uptimeMillis. * The time-base is {@link android.os.SystemClock#uptimeMillis}. * The runnable will be run on the thread to which this handler is attached. * * @param r The Runnable that will be executed. * @param uptimeMillis The absolute time at which the callback should run, * using the {@link android.os.SystemClock#uptimeMillis} time-base. * * @return Returns true if the Runnable was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. Note that a * result of true does not mean the Runnable will be processed -- if * the looper is quit before the delivery time of the message * occurs then the message will be dropped. * * @see android.os.SystemClock#uptimeMillis */ public final boolean postAtTime(Runnable r, Object token, long uptimeMillis) { return sendMessageAtTime(getPostMessage(r, token), uptimeMillis); } /*** * Causes the Runnable r to be added to the message queue, to be run * after the specified amount of time elapses. * The runnable will be run on the thread to which this handler * is attached. * * @param r The Runnable that will be executed. * @param delayMillis The delay (in milliseconds) until the Runnable * will be executed. * * @return Returns true if the Runnable was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. Note that a * result of true does not mean the Runnable will be processed -- * if the looper is quit before the delivery time of the message * occurs then the message will be dropped. */ public final boolean postDelayed(Runnable r, long delayMillis) { return sendMessageDelayed(getPostMessage(r), delayMillis); } /*** * Posts a message to an object that implements Runnable. * Causes the Runnable r to executed on the next iteration through the * message queue. The runnable will be run on the thread to which this * handler is attached. * This method is only for use in very special circumstances -- it * can easily starve the message queue, cause ordering problems, or have * other unexpected side-effects. * * @param r The Runnable that will be executed. * * @return Returns true if the message was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. */ public final boolean postAtFrontOfQueue(Runnable r) { return sendMessageAtFrontOfQueue(getPostMessage(r)); } /*** * Remove any pending posts of Runnable r that are in the message queue. */ //直接从消息队列中移除 public final void removeCallbacks(Runnable r) { mQueue.removeMessages(this, r, null); } /*** * Remove any pending posts of Runnable r with Object * token that are in the message queue. If token is null, * all callbacks will be removed. */ public final void removeCallbacks(Runnable r, Object token) { mQueue.removeMessages(this, r, token); } /*** * Pushes a message onto the end of the message queue after all pending messages * before the current time. It will be received in {@link #handleMessage}, * in the thread attached to this handler. * * @return Returns true if the message was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. */ //将一个消息推到消息队列的末端 public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); } /*** * Sends a Message containing only the what value. * * @return Returns true if the message was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. */ public final boolean sendEmptyMessage(int what) { return sendEmptyMessageDelayed(what, 0); } /*** * Sends a Message containing only the what value, to be delivered * after the specified amount of time elapses. * @see #sendMessageDelayed(android.os.Message, long) * * @return Returns true if the message was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. */ public final boolean sendEmptyMessageDelayed(int what, long delayMillis) { Message msg = Message.obtain(); msg.what = what; return sendMessageDelayed(msg, delayMillis); } /*** * Sends a Message containing only the what value, to be delivered * at a specific time. * @see #sendMessageAtTime(android.os.Message, long) * * @return Returns true if the message was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. */ public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) { Message msg = Message.obtain(); msg.what = what; return sendMessageAtTime(msg, uptimeMillis); } /*** * Enqueue a message into the message queue after all pending messages * before (current time + delayMillis). You will receive it in * {@link #handleMessage}, in the thread attached to this handler. * * @return Returns true if the message was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. Note that a * result of true does not mean the message will be processed -- if * the looper is quit before the delivery time of the message * occurs then the message will be dropped. */ //其调用了endMessageAtTime,也是将一个消息入队而已,时间靠什么定义而已 public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); } /*** * Enqueue a message into the message queue after all pending messages * before the absolute time (in milliseconds) uptimeMillis. * The time-base is {@link android.os.SystemClock#uptimeMillis}. * You will receive it in {@link #handleMessage}, in the thread attached * to this handler. * * @param uptimeMillis The absolute time at which the message should be * delivered, using the * {@link android.os.SystemClock#uptimeMillis} time-base. * * @return Returns true if the message was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. Note that a * result of true does not mean the message will be processed -- if * the looper is quit before the delivery time of the message * occurs then the message will be dropped. */ //将消息根据时间等入队 public boolean sendMessageAtTime(Message msg, long uptimeMillis) { boolean sent = false; MessageQueue queue = mQueue; if (queue != null) { //target对象,嗯 msg.target = this; //将该消息入队 sent = queue.enqueueMessage(msg, uptimeMillis); } else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent; } /*** * Enqueue a message at the front of the message queue, to be processed on * the next iteration of the message loop. You will receive it in * {@link #handleMessage}, in the thread attached to this handler. * This method is only for use in very special circumstances -- it * can easily starve the message queue, cause ordering problems, or have * other unexpected side-effects. * * @return Returns true if the message was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. */ public final boolean sendMessageAtFrontOfQueue(Message msg) { boolean sent = false; MessageQueue queue = mQueue; if (queue != null) { msg.target = this; //将该消息入队,且为队首 sent = queue.enqueueMessage(msg, 0); } else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent; } /*** * Remove any pending posts of messages with code 'what' that are in the * message queue. */ public final void removeMessages(int what) { mQueue.removeMessages(this, what, null, true); } /*** * Remove any pending posts of messages with code 'what' and whose obj is * 'object' that are in the message queue. If token is null, * all messages will be removed. */ public final void removeMessages(int what, Object object) { mQueue.removeMessages(this, what, object, true); } /*** * Remove any pending posts of callbacks and sent messages whose * obj is token. If token is null, * all callbacks and messages will be removed. */ public final void removeCallbacksAndMessages(Object token) { mQueue.removeCallbacksAndMessages(this, token); } /*** * Check if there are any pending posts of messages with code 'what' in * the message queue. */ public final boolean hasMessages(int what) { return mQueue.removeMessages(this, what, null, false); } /*** * 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.removeMessages(this, what, object, false); } // 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)) + "}"; } //IMessenger是个什么东西,一个远程消息对象,这个可以实现进程间基于消息的通信 final IMessenger getIMessenger() { synchronized (mQueue) { if (mMessenger != null) { return mMessenger; } mMessenger = new MessengerImpl(); return mMessenger; } } //原来在这里,是一个内部类,只实现了一个send方法 private final class MessengerImpl extends IMessenger.Stub { public void send(Message msg) { //把handler传递给远程对象,远程对象直接向该handler发送消息,真简单额 Handler.this.sendMessage(msg); } } //将runnable转换为message,,,,message拥有一个callback,我擦这样啊,变态玩意 private final Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m; } private final Message getPostMessage(Runnable r, Object token) { Message m = Message.obtain(); m.obj = token; m.callback = r; return m; } //处理消息的回调,调用message的callback的run方法,因为callback是一个runnable private final void handleCallback(Message message) { message.callback.run(); } //消息队列 消息循环 回调 messenger对象 //handler是与这些进行绑定的 final MessageQueue mQueue; final Looper mLooper; //这个是内部的接口 final Callback mCallback; IMessenger mMessenger; }