Handler的关键方法:
-
obatinMessage系列方法
- Message obtainMessage()
- Message obtainMessage(int what)
- Message obtainMessage(int what, Object obj)
- Message obtainMessage(int what, int arg1, int arg2)
- Message obtainMessage(int what, int arg1, int arg2, Object obj)
该系列方法内部调用了Message的obatin()系列方法,并把自己这个handler对象传给Message的Handler target,那这种方式创建的消息则指定由target指向的handler处理(如果发送的handler和创建消息的handler不是同一个,以发送的为准)。
-
post系列方法
- boolean post(Runnable r) 立即执行 内部调用了return sendMessageDelayed(getPostMessage(r), 0); 延迟时间为0
- boolean postAtTime(Runnable r, long uptimeMillis) 在指定时间执行
- boolean postAtTime(Runnable r, Object obj, long uptimeMillis) 在指定时间执行, r赋给Message的callback, obj赋给Message的obj
- boolean postDelayed(Runnable r, long delayMillis) 延迟指定时间执行,如果延迟时间传的值小于0,则相当于立即执行,delayMillis会重置为0,然后调用sendMessageAtTime
- boolean postAtFrontOfQueue(Runnable r)
注意:延迟时间或者指定时间是不一定准的,在注释中有说明,深度休眠会影响消息处理。
另外,该系列方法的返回值都是布尔类型,如果Runnable已成功放入消息队列,则返回true。 失败时返回false,通常是因为处理消息队列的looper正在退出。 请注意,结果为true并不意味着将处理Runnable - 如果在消息发送时间之前退出looper,则消息将被丢弃。
因为post系列方法内部都是使用send系列方法,所以其实最终,post系列也是使用sendMessageAtTime(Message msg, long uptimeMillis)
-
send系列方法
- boolean sendMessage(Message msg)
- boolean sendEmptyMessage(int what)
- boolean sendEmptyMessageDelayed(int what, long delayMillis)
- boolean sendEmptyMessageAtTime(int what, long uptimeMillis)
- boolean sendMessageDelayed(Message msg, long delayMillis)
- boolean sendMessageAtTime(Message msg, long uptimeMillis)
send系列方法最终都会调用sendMessageAtTime(Message msg, long uptimeMillis)。
立即执行的会调用sendMessageDelayed(msg, 0), 而sendMessageDelayed(Message msg , long delayMillis) 会调用sendMessageAtiTime(Message msg, long uptimeMillis),并将延迟时间转换为确定时间SystemClock.uptimeMillis() + delayMillis
-
知识点总结
-
post系列方法和send系列方法最终都会调用sendMessageAtTime(Message message, long uptimeMillis), 将延迟时间转换为未来的确定时间。post系列方法接收Runnable参数,最后还是调用sendMessageAtTime(Message message, long uptimeMillis),在post内部,从消息池中获取了一个Message对象,并把Runnable参数赋值给Message对象的callback属性。所以说,post系列方法其实最终也是走的send系列方法,不一样的是post最终发送的Message的callback属性一定有值,send系列除非传进来的我们创建的Message带有callback
public final boolean post(Runnable r) { //调用sendMessageDelayed()方法,第一个参数是调用getPostMessage(Runnable r)方法将runnable对象转为Message对象,第二个参数是延迟时间 return sendMessageDelayed(getPostMessage(r), 0); } //看一下getPostMessage(Runnable r)方法 private static Message getPostMessage(Runnable r) { //从消息池中获取消息 Message m = Message.obtain(); //将runnable对象赋给Message对象的callback属性 m.callback = r; return m; }
-
空消息是指Message中只有what属性值得消息
-
使用obtainMessage()方法构建消息其实内部调用了Message.obtain(),只是obtainMessage()方法中handler将自己赋值给了Message的target属性, 其实当我们调用sendMessageAtTime(..)时,内部会调用Handler的enqueueMessage()方法,在这个方法内部做了两件事,第一就是将本handler赋给Message的target属性,第二就是调用MessageQueue的enqueue()方法,如下代码所示
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; } //调用enqueMessage(MessageQueue queue, Message msg, long uptimeMillis),分析见下方方法 return enqueueMessage(queue, msg, uptimeMillis); } private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { //将调用send或者post的Handler对象赋值给Message对象的target属性 msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } //调用消息队列的enqueueMessage()方法 return queue.enqueueMessage(msg, uptimeMillis); }
那如果我们在创建消息的时候使用handler1.obtainMessage()方法,然后发送的时候使用handler2.sendMessage(),最终是谁收到消息呢? 看上面的enqueueMessage()方法便知会是handler2收到消息,在sendMessage的时候会把obtainMessage()中给Message赋的target给改掉。
-
延迟时间或者指定时间是不一定准的,在注释中有说明,深度休眠会影响消息处理。
-
延迟指定时间执行,如果延迟时间传的值小于0,则相当于立即执行,当检查delayMillis小于0时,会把它重置为0,然后调用sendMessageAtTime(message, SystemClock.uptimeMillis() + 0),即立即执行
-
post系列方法和send系列方法的返回值都是布尔类型,如果Runnable或者Message已成功放入消息队列,则返回true。 失败时返回false,通常是因为处理消息队列的looper正在退出。 注意,结果为true并不意味着一定会处理Runnable或者Message,如果在消息发送时间之前退出looper,则消息将被丢弃。
-
/**
* 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.
*Handler允许您发送和处理与线程的MessageQueue关联的消息和Runnable对象。 每个Handler实例都与一个线程和该线程的消息队列相关联。 当您创建一个新的Handler时,它被绑定到正在创建它的线程的线程消息队列 - 从那时起,它将消息和runnables传递给该消息队列并在它们从消息队列中出来时执行它们
* <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.
* Handler有两个主要用途:(1)调度消息和runnables,在未来某个时间点执行; (2)将要在不同于自己的线程上执行的操作排入队列
* <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).
使用post,postAtTime(Runnable,long),postDelayed,sendEmptyMessage,sendMessage,sendMessageAtTime和sendMessageDelayed方法完成调度消息。 post系列方法允许您将Runnable对象排入队列,以便在收到它们时由消息队列调用; sendMessage系列方法允许您将包含将由Handler的handleMessage方法处理的数据包的Message对象排入队列(要求您实现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.
* 当post或者send一个消息到handler时,您可以在消息队列准备好后立即允许处理该项目(立即发送postRunnable,sendMessage,即延时为0),或者在处理之前指定延迟或者处理它的绝对时间。 后两者允许您实现超时,滴答和其他基于时间的行为。延迟方法其实最后调用的是绝对时间方法,两者可以转换。
* <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.
为应用程序创建进程时,其主线程专用于运行消息队列,该队列负责管理顶级应用程序对象(活动,广播接收器等)及其创建的任何窗口。 您可以创建自己的线程,并通过Handler与主应用程序线程进行通信。 这是通过调用与以前相同的post或sendMessage方法完成的,但是来自您的新线程。 然后,将在Handler的消息队列中调度给定的Runnable或Message,并在适当时进行处理。
*/
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.
将此标志设置为true可以检测扩展此Handler本地或成员类并且它们不是静态的匿名。 这些类可能会造成泄漏。现在在AndroidStudio中,如果使用handler不正确,可能会产生内存泄漏的话,会有提示,其实就是将这个标志打开了,然后在构造方法中检查这个标志位为true,然后有提示,可以看下方的构造函数的源码
*/
private static final boolean FIND_POTENTIAL_LEAKS = false;//find_potential_leaks发现潜在的泄漏
private static final String TAG = "Handler";
private static Handler MAIN_THREAD_HANDLER = null;
/**
* Callback interface you can use when instantiating a Handler to avoid
* having to implement your own subclass of Handler.在实例化Handler时可以使用的回调接口,以避免必须实现自己的Handler子类。
比如:
import android.os.Handler.Callback;
public class CallWrapper impelments Callback{
}
*/
public interface Callback {
/**
* @param msg A {@link android.os.Message Message} object
* @return True if no further handling is desired 如果不需要进一步处理,则返回True
*/
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.默认构造函数将此处理程序与当前线程的Looper相关联。 如果此线程没有looper,则此处理程序将无法接收消息,因此会引发异常。
*/
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.
构造函数将此处理程序与当前线程的Looper相关联,并采用一个回调接口来处理消息。如果此线程没有looper,则此处理程序将无法接收消息,因此抛出异常.callback 用于处理消息的回调接口,或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.
*将Looper用于当前线程并设置处理程序是否应该是异步的。默认情况下,处理程序是同步的,除非使用此构造函数来生成严格异步的处理程序。
异步消息表示不需要针对同步消息进行全局排序的中断或事件。 异步消息不受MessageQueue enqueueSyncBarrier(long)引入的同步障碍的影响。
@param async如果为true,则处理程序为发送给它的每个{@link Message}或发布到它的{@link Runnable}调用Message.setAsynchronous(boolean)。
* @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) {
//经常在编译器见到的warning
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;
}
/** @hide */
@NonNull
public static Handler getMain() {
if (MAIN_THREAD_HANDLER == null) {
MAIN_THREAD_HANDLER = new Handler(Looper.getMainLooper());
}
return MAIN_THREAD_HANDLER;
}
/** @hide */
@NonNull
public static Handler mainIfNull(@Nullable Handler handler) {
return handler == null ? getMain() : handler;
}
/** {@hide} */
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();
}
/**
* 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.
从全局消息池返回新的{@link android.os.Message Message}。 比创建和分配新实例更有效。 检索到的消息将其处理程序设置为此实例(Message.target == this)。如果您不想要该工具,请改为调用Message.obtain()。
*/
public final Message obtainMessage()
{
//调用了Message.obtain(Handler handler),把自己作为参数传递了进去,相当于用Handler.obtainMessage()创建的消息指定了处理者是调用对象handler,可以看到obtain系列的方法内部调用Message的obtain系列方法,并把自己传入
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 r被添加到消息队列中。可运行的操作将在此处理程序所连接的线程上运行。
@param r将执行的Runnable。
@return如果Runnable已成功放入消息队列,则返回true。 失败时返回false,通常是因为处理消息队列的looper正在退出。
*/
public final boolean post(Runnable r)
{
//post内部实际是调用了sendMessageDelayed(),只不过延迟时间设置的是0,也就是立即发送
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.
Runnable r被添加到消息队列中,以便在uptimeMillis给定的特定时间运行。时间取决于{@link android.os.SystemClock#uptimeMillis}。
深度睡眠所花费的时间会给执行带来额外的延迟。(所以延迟执行不一定真的会按照你的延迟时间准时执行)
runnable将在连接此处理程序的线程上运行。
@param r将执行的Runnable。
param uptimeMillis使用{@link android.os.SystemClock#uptimeMillis}时基运行回调的绝对时间。
@return如果Runnable已成功放入消息队列,则返回true。 失败时返回false,通常是因为处理消息队列的looper正在退出。 请注意,结果为true并不意味着将处理Runnable - 如果在消息发送时间之前退出looper,则消息将被丢弃。
*/
public final boolean postAtTime(Runnable r, long uptimeMillis)
{
//调用sendMessageAtTime(),对于getPostMessage(Runnable r),,其实就是创建了一个Message,并把这个runnable赋给message的callback, 见下面对sendMessageAtTime以及getPostMessage分析
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
关于参数token,其实类似于Message带object参数,在getPostMessage(r, token)内部,创建一个Message对象,将runnable赋给Message对象的callback,将token赋给Message对象的obj
*/
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.
将消息发布到实现Runnable的对象。
导致Runnable r在下一次迭代中执行
消息队列。 runnable将在连接此处理程序的线程上运行。
此方法仅用于非常特殊的情况 - 它可能很容易使消息队列饿死,导致排序问题或具有其他意外的副作用。
@param r将执行的Runnable。
@return如果消息已成功放入消息队列,则返回true。 失败时返回false,通常是因为处理消息队列的looper正在退出。
*/
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.
移除消息队列里面指定的runnable
*/
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.
将消息推送到在当前时间之前的所有待处理消息之后消息队列的末尾。 它将在{@link #handleMessage}中,在附加到此处理程序的线程中接收。
@return如果消息已成功放入消息队列,则返回true。 失败时返回false,通常是因为处理消息队列的looper正在退出。
*/
public final boolean sendMessage(Message msg)
{
//内部调用sendMessageDelayed(Message msg, long delayMillis)方法
return sendMessageDelayed(msg, 0);
}
/**
* Sends a Message containing only the what value.
* 发送仅带what参数的一个Message,不携带obj,arg1,arg2
* @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)
{
//内部调用sendEmptyMessageDelayed(int what, long delayMillis)
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对象,给其what属性赋值,然后调用sendMessageDelayed(Message msg, 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) {
//如果延迟时间传的值小于0,则相当于立即执行,delayMillis为0
delayMillis = 0;
}
//延迟方式其实是转换成了指定确定时间方式执行,调用sendMessageAtTime,在第二个参数中做了转换,当前时间+延迟时间 转换成指定确定时间执行
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.
在绝对时间(以毫秒为单位)uptimeMillis之前,所有待处理消息之后将消息排入消息队列。
时基是{@link android.os.SystemClock#uptimeMillis}。
深度睡眠所花费的时间会给执行带来额外的延迟。
您将在附加到此处理程序的线程中的{@link #handleMessage}中收到它。
@param uptimeMillis使用{@link android.os.SystemClock#uptimeMillis}时基传递消息的绝对时间。
@return如果消息已成功放入消息队列,则返回true。 失败时返回false,通常是因为处理消息队列的looper正在退出。 请注意,结果为true并不意味着将处理消息 - 如果在消息的传递时间之前退出looper,则消息将被丢弃。
*/
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;
}
//调用enqueMessage(MessageQueue queue, Message msg, long uptimeMillis),分析见下方方法
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);
}
//sendMessageAtTime()的主要逻辑
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
//可以看出来,其实就算不是使用handler.obtainMessage,在这个地方也会给message的target属性设为本handler
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
//核心是调用消息队列的enqueueMessage(Message msg, long uptimeMisllis)方法
return queue.enqueueMessage(msg, uptimeMillis);
}
/**
* Remove any pending posts of messages with code 'what' that are in the
* message queue.
移除指定what的Message
*/
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.
检查消息队列中是否有指定what的Message
*/
public final boolean hasMessages(int what) {
return mQueue.hasMessages(this, what, null);
}
/**
* Return whether there are any messages or callbacks currently scheduled on this handler.
* @hide
消息队列中是否含有指定本handler处理的消息
*/
public final boolean hasMessagesOrCallbacks() {
return mQueue.hasMessages(this);
}
/**
* 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 + " ");
}
}
/**
* @hide
*/
public final void dumpMine(Printer pw, String prefix) {
pw.println(prefix + this + " @ " + SystemClock.uptimeMillis());
if (mLooper == null) {
pw.println(prefix + "looper uninitialized");
} else {
mLooper.dump(pw, prefix + " ", this);
}
}
@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 Looper mLooper;
final MessageQueue mQueue;
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;
}
}
}
网友评论