Handler 源码解析
线上Handler类源码
/* * 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; /** * A Handler allows you to send and process {@link Message} and Runnable * objects associated with a thread's {@link MessageQueue}. Each Handler * instance is associated with a single thread and that thread's message * queue. When you create a new Handler, it is bound to the thread / * message queue of the thread that is creating it -- from that point on, * it will deliver messages and runnables to that message queue and execute * them as they come out of the message queue. * * <p>There are two main uses for a Handler: (1) to schedule messages and * runnables to be executed as some point in the future; and (2) to enqueue * an action to be performed on a different thread than your own. * * <p>Scheduling messages is accomplished with the * {@link #post}, {@link #postAtTime(Runnable, long)}, * {@link #postDelayed}, {@link #sendEmptyMessage}, * {@link #sendMessage}, {@link #sendMessageAtTime}, and * {@link #sendMessageDelayed} methods. The <em>post</em> versions allow * you to enqueue Runnable objects to be called by the message queue when * they are received; the <em>sendMessage</em> versions allow you to enqueue * a {@link Message} object containing a bundle of data that will be * processed by the Handler's {@link #handleMessage} method (requiring that * you implement a subclass of Handler). * * <p>When posting or sending to a Handler, you can either * allow the item to be processed as soon as the message queue is ready * to do so, or specify a delay before it gets processed or absolute time for * it to be processed. The latter two allow you to implement timeouts, * ticks, and other timing-based behavior. * * <p>When a * process is created for your application, its main thread is dedicated to * running a message queue that takes care of managing the top-level * application objects (activities, broadcast receivers, etc) and any windows * they create. You can create your own threads, and communicate back with * the main application thread through a Handler. This is done by calling * the same <em>post</em> or <em>sendMessage</em> methods as before, but from * your new thread. The given Runnable or Message will then be scheduled * in the Handler's message queue and processed when appropriate. */ 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. * * @param msg A {@link android.os.Message Message} object * @return True if no further handling is desired */ public interface Callback { public boolean handleMessage(Message msg); } /** * Subclasses must implement this to receive messages. */ public void handleMessage(Message msg) { } /** * Handle system messages here. */ public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } } /** * Default constructor associates this handler with the {@link Looper} for the * current thread. * * If this thread does not have a looper, this handler won't be able to receive messages * so an exception is thrown. */ public Handler() { this(null, false); } /** * Constructor associates this handler with the {@link Looper} for the * current thread and takes a callback interface in which you can handle * messages. * * If this thread does not have a looper, this handler won't be able to receive messages * so an exception is thrown. * * @param callback The callback interface in which to handle messages, or null. */ public Handler(Callback callback) { this(callback, false); } /** * Use the provided {@link Looper} instead of the default one. * * @param looper The looper, must not be null. */ public Handler(Looper looper) { this(looper, null, false); } /** * Use the provided {@link Looper} instead of the default one and take a callback * interface in which to handle messages. * * @param looper The looper, must not be null. * @param callback The callback interface in which to handle messages, or null. */ public Handler(Looper looper, Callback callback) { this(looper, callback, false); } /** * Use the {@link Looper} for the current thread * and set whether the handler should be asynchronous. * * Handlers are synchronous by default unless this constructor is used to make * one that is strictly asynchronous. * * Asynchronous messages represent interrupts or events that do not require global ordering * with respect to synchronous messages. Asynchronous messages are not subject to * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}. * * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for * each {@link Message} that is sent to it or {@link Runnable} that is posted to it. * * @hide */ public Handler(boolean async) { this(null, async); } /** * Use the {@link Looper} for the current thread with the specified callback interface * and set whether the handler should be asynchronous. * * Handlers are synchronous by default unless this constructor is used to make * one that is strictly asynchronous. * * Asynchronous messages represent interrupts or events that do not require global ordering * with respect to synchronous messages. Asynchronous messages are not subject to * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}. * * @param callback The callback interface in which to handle messages, or null. * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for * each {@link Message} that is sent to it or {@link Runnable} that is posted to it. * * @hide */ 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; } /** * Use the provided {@link Looper} instead of the default one and take a callback * interface in which to handle messages. Also set whether the handler * should be asynchronous. * * Handlers are synchronous by default unless this constructor is used to make * one that is strictly asynchronous. * * Asynchronous messages represent interrupts or events that do not require global ordering * with respect to synchronous messages. Asynchronous messages are not subject to * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}. * * @param looper The looper, must not be null. * @param callback The callback interface in which to handle messages, or null. * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for * each {@link Message} that is sent to it or {@link Runnable} that is posted to it. * * @hide */ public Handler(Looper looper, Callback callback, boolean async) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async; } /** * 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 */ 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. */ 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. */ 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 <var>uptimeMillis</var>. * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b> * Time spent in deep sleep will add an additional delay to execution. * 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 <var>uptimeMillis</var>. * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b> * Time spent in deep sleep will add an additional delay to execution. * 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. * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b> * Time spent in deep sleep will add an additional delay to execution. * * @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. * <b>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.</b> * * @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)); } /** * Runs the specified task synchronously. * <p> * If the current thread is the same as the handler thread, then the runnable * runs immediately without being enqueued. Otherwise, posts the runnable * to the handler and waits for it to complete before returning. * </p><p> * This method is dangerous! Improper use can result in deadlocks. * Never call this method while any locks are held or use it in a * possibly re-entrant manner. * </p><p> * This method is occasionally useful in situations where a background thread * must synchronously await completion of a task that must run on the * handler's thread. However, this problem is often a symptom of bad design. * Consider improving the design (if possible) before resorting to this method. * </p><p> * One example of where you might want to use this method is when you just * set up a Handler thread and need to perform some initialization steps on * it before continuing execution. * </p><p> * If timeout occurs then this method returns <code>false</code> but the runnable * will remain posted on the handler and may already be in progress or * complete at a later time. * </p><p> * When using this method, be sure to use {@link Looper#quitSafely} when * quitting the looper. Otherwise {@link #runWithScissors} may hang indefinitely. * (TODO: We should fix this by making MessageQueue aware of blocking runnables.) * </p> * * @param r The Runnable that will be executed synchronously. * @param timeout The timeout in milliseconds, or 0 to wait indefinitely. * * @return Returns true if the Runnable was successfully executed. * Returns false on failure, usually because the * looper processing the message queue is exiting. * * @hide This method is prone to abuse and should probably not be in the API. * If we ever do make it part of the API, we might want to rename it to something * less funny like runUnsafe(). */ 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); } /** * 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 <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); } /** * 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. */ 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) <var>uptimeMillis</var>. * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b> * Time spent in deep sleep will add an additional delay to execution. * 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) { 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); } /** * 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. * <b>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.</b> * * @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) { 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); } private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); } /** * 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); } /** * Remove any pending posts of messages with code 'what' and whose obj is * 'object' that are in the message queue. If <var>object</var> is null, * all messages will be removed. */ public final void removeMessages(int what, Object object) { mQueue.removeMessages(this, what, object); } /** * Remove any pending posts of callbacks and sent messages whose * <var>obj</var> is <var>token</var>. If <var>token</var> 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.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); } /** * Check if there are any pending posts of messages with callback r in * the message queue. * * @hide */ 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)) + "}"; } final IMessenger getIMessenger() { synchronized (mQueue) { if (mMessenger != null) { return mMessenger; } mMessenger = new MessengerImpl(); return mMessenger; } } private final class MessengerImpl extends IMessenger.Stub { public void send(Message msg) { msg.sendingUid = Binder.getCallingUid(); Handler.this.sendMessage(msg); } } private static Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m; } private static Message getPostMessage(Runnable r, Object token) { Message m = Message.obtain(); m.obj = token; m.callback = r; return m; } private static void handleCallback(Message message) { message.callback.run(); } final MessageQueue mQueue; final Looper mLooper; final Callback mCallback; final boolean mAsynchronous; IMessenger mMessenger; private static final class BlockingRunnable implements Runnable { private final Runnable mTask; private boolean mDone; public BlockingRunnable(Runnable task) { mTask = task; } @Override public void run() { try { mTask.run(); } finally { synchronized (this) { mDone = true; notifyAll(); } } } public boolean postAndWait(Handler handler, long timeout) { if (!handler.post(this)) { return false; } synchronized (this) { if (timeout > 0) { final long expirationTime = SystemClock.uptimeMillis() + timeout; while (!mDone) { long delay = expirationTime - SystemClock.uptimeMillis(); if (delay <= 0) { return false; // timeout } try { wait(delay); } catch (InterruptedException ex) { } } } else { while (!mDone) { try { wait(); } catch (InterruptedException ex) { } } } } return true; } } }是在android.os 包下
package android.os;
首先是两个静态常量
/* * 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";
第二个就是一个TAG,打log区分用的,这个不多介绍了
第一个是说是个 可能存在潜在内存泄漏的标示,有道翻译如下:
这个标志设置为真正的匿名检测,本地或类成员
扩展处理程序类,不是静态的。这类
类可以创建的泄漏
再往下是个接口
/** * Callback interface you can use when instantiating a Handler to avoid * having to implement your own subclass of Handler. * * @param msg A {@link android.os.Message Message} object * @return True if no further handling is desired */ public interface Callback { public boolean handleMessage(Message msg); }这个CallBack接口可以咱们在类中实现,就不需要在继承Handler了
这个handleMessage方法如果返回true的话,就不会再有更多的处理,后续会对这里解释一下。
再往下
/** * Subclasses must implement this to receive messages. */ public void handleMessage(Message msg) { }这个来了,子类必须实现的方法,来接收消息,注解里写的, 我翻译一下。
再往下
/** * Handle system messages here. */ public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }分发消息,消息来了之后第一处理的是消息本身的callback这个属性是否有值。
/*package*/ Runnable callback;这个是Message中的callBack, 是一个Runnable对象。
其实这个就是,Handler发送post了一个Runnable对象。这里的意思是如果post的是Runnable对象那么就直接执行HandleCallBack(msg)了,看看是什么
private static void handleCallback(Message message) { message.callback.run(); }就是直接在这个线程中执行了run()方法。在主线程执行的哦!!!
然后再看dispatchMessage方法,如不是Runnable的话,判断是否mCallBack属性是否为null,是此handler对象的mCallBack属性
final Callback mCallback;这个属性
实现就是开始那个
public interface Callback { public boolean handleMessage(Message msg); }如果有这个属性被赋值的话,就直接执行了handlerMessage这个实现的方法。是哪个类实现的,就在哪个类里执行。
如果这些都为null的话,就执行下面这个了。
/** * Subclasses must implement this to receive messages. */ public void handleMessage(Message msg) { }
/** * Handle system messages here. */ public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
这个dispatchMessage 齐活,知道它是干什么的了。
再往下看源码:构造方法
/** * Default constructor associates this handler with the {@link Looper} for the * current thread. * * If this thread does not have a looper, this handler won't be able to receive messages * so an exception is thrown. */ public Handler() { this(null, false); }
/** * Constructor associates this handler with the {@link Looper} for the * current thread and takes a callback interface in which you can handle * messages. * * If this thread does not have a looper, this handler won't be able to receive messages * so an exception is thrown. * * @param callback The callback interface in which to handle messages, or null. */ public Handler(Callback callback) { this(callback, false); }
/** * Use the provided {@link Looper} instead of the default one. * * @param looper The looper, must not be null. */ public Handler(Looper looper) { this(looper, null, false); }
/** * Use the provided {@link Looper} instead of the default one and take a callback * interface in which to handle messages. * * @param looper The looper, must not be null. * @param callback The callback interface in which to handle messages, or null. */ public Handler(Looper looper, Callback callback) { this(looper, callback, false); }
/** * Use the {@link Looper} for the current thread * and set whether the handler should be asynchronous. * * Handlers are synchronous by default unless this constructor is used to make * one that is strictly asynchronous. * * Asynchronous messages represent interrupts or events that do not require global ordering * with respect to synchronous messages. Asynchronous messages are not subject to * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}. * * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for * each {@link Message} that is sent to it or {@link Runnable} that is posted to it. * * @hide */ public Handler(boolean async) { this(null, async); }
/** * Use the {@link Looper} for the current thread with the specified callback interface * and set whether the handler should be asynchronous. * * Handlers are synchronous by default unless this constructor is used to make * one that is strictly asynchronous. * * Asynchronous messages represent interrupts or events that do not require global ordering * with respect to synchronous messages. Asynchronous messages are not subject to * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}. * * @param callback The callback interface in which to handle messages, or null. * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for * each {@link Message} that is sent to it or {@link Runnable} that is posted to it. * * @hide */ 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; }
/** * Use the provided {@link Looper} instead of the default one and take a callback * interface in which to handle messages. Also set whether the handler * should be asynchronous. * * Handlers are synchronous by default unless this constructor is used to make * one that is strictly asynchronous. * * Asynchronous messages represent interrupts or events that do not require global ordering * with respect to synchronous messages. Asynchronous messages are not subject to * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}. * * @param looper The looper, must not be null. * @param callback The callback interface in which to handle messages, or null. * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for * each {@link Message} that is sent to it or {@link Runnable} that is posted to it. * * @hide */ public Handler(Looper looper, Callback callback, boolean async) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async; }基本上是重载的,后面两个有一些内容。
其实就是对下面这四个值进行赋值。
mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async;倒数第二个的构造方法加了一些日志打印的判断,和looper的判断。
有一个这个需要解释下
mLooper = Looper.myLooper();这个意思是从当前线程中取出looper对象来,如果没有的话说明当前的线程不能使用Handler机制
在UI线程中是系统创建好了Looper对象了。在子线程要么自己实现,用么用HandlerThread给你实现好的 。
这个Looper的具体介绍后续会在Looper专门源码解析地方讲解。
/** * 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 */ public String getMessageName(Message message) { if (message.callback != null) { return message.callback.getClass().getName(); } return "0x" + Integer.toHexString(message.what); }上面这个是获取message的名称,如果Message.callback对象不为null就取这个callback的名字,这个callback其实就是上面提到的Runnable对象
/*package*/ Runnable callback;如果这个callback为null,就讲message.what这个属性值加上"0x"开头返回,这个值是咱们区分handler处理消息的类型的,一个int类型的属性
/** * User-defined message code so that the recipient can identify * what this message is about. Each {@link Handler} has its own name-space * for message codes, so you do not need to worry about yours conflicting * with other handlers. */ public int 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. */ 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); }
然后继续,是obtainMessge()方法,这个是不重复创建Message对象而设计的,在Message中有个message对象池,可以重复使用里边东西,对对象重复创建进行优化,里边具体的代码解析,在Message源码解析那里会详细介绍。
记得这些获得message的方法,在Handler中存在,在Message也存在,Handler中的方法是直接的调用Message中的。
再继续看代码:
/** * 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. */ 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 <var>uptimeMillis</var>. * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b> * Time spent in deep sleep will add an additional delay to execution. * 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 <var>uptimeMillis</var>. * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b> * Time spent in deep sleep will add an additional delay to execution. * 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. * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b> * Time spent in deep sleep will add an additional delay to execution. * * @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. * <b>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.</b> * * @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)); }
上面这些都是post方法,参数都是Runnable对象,最终调用的都是转换成一个带时间的参数,延迟多久执行,延迟0s的话就是直接执行了。
再继续
/** * 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 <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); }这连个是移除Runnable的Message对象,要取消postMessage可以执行者两个
再往下看
/** * 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. */ 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) <var>uptimeMillis</var>. * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b> * Time spent in deep sleep will add an additional delay to execution. * 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) { 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); } /** * 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. * <b>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.</b> * * @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) { 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); }上面这些都是发送消息的。也是按延迟时间来发送的,有的需要立即处理的,就延迟时间为0了,不需要的加上time这个参数就可以了,这些事重载的方法,这里执行到最后都是enqueueMessage方法,看看去
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,设置这个msg是否为异步的。然后放到了消息队列中。跑里头排队去了,等到MessageQueue解析的时候在分析里边吧。
再下面是
/** * 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); } /** * Remove any pending posts of messages with code 'what' and whose obj is * 'object' that are in the message queue. If <var>object</var> is null, * all messages will be removed. */ public final void removeMessages(int what, Object object) { mQueue.removeMessages(this, what, object); } /** * Remove any pending posts of callbacks and sent messages whose * <var>obj</var> is <var>token</var>. If <var>token</var> 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.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); } /** * Check if there are any pending posts of messages with callback r in * the message queue. * * @hide */ 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)) + "}"; } final IMessenger getIMessenger() { synchronized (mQueue) { if (mMessenger != null) { return mMessenger; } mMessenger = new MessengerImpl(); return mMessenger; } } private final class MessengerImpl extends IMessenger.Stub { public void send(Message msg) { msg.sendingUid = Binder.getCallingUid(); Handler.this.sendMessage(msg); } } private static Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m; } private static Message getPostMessage(Runnable r, Object token) { Message m = Message.obtain(); m.obj = token; m.callback = r; return m; } private static void handleCallback(Message message) { message.callback.run(); } final MessageQueue mQueue; final Looper mLooper; final Callback mCallback; final boolean mAsynchronous; IMessenger mMessenger; private static final class BlockingRunnable implements Runnable { private final Runnable mTask; private boolean mDone; public BlockingRunnable(Runnable task) { mTask = task; } @Override public void run() { try { mTask.run(); } finally { synchronized (this) { mDone = true; notifyAll(); } } } public boolean postAndWait(Handler handler, long timeout) { if (!handler.post(this)) { return false; } synchronized (this) { if (timeout > 0) { final long expirationTime = SystemClock.uptimeMillis() + timeout; while (!mDone) { long delay = expirationTime - SystemClock.uptimeMillis(); if (delay <= 0) { return false; // timeout } try { wait(delay); } catch (InterruptedException ex) { } } } else { while (!mDone) { try { wait(); } catch (InterruptedException ex) { } } } } return true; } }