Handler

来源:互联网 发布:防广告弹出软件 编辑:程序博客网 时间:2024/06/14 23:51

原文地址:http://blog.csdn.net/wcs542882916

packageandroid.os;

 

importandroid.util.Log;

importandroid.util.Printer;

 

importjava.lang.reflect.Modifier;

importandroid.os.Process;

importjava.util.Iterator;

import android.os.Process;

 

/**

 * AHandler allows you to send and process{@link Message} and Runnable objects

 *associated with a thread's {@linkMessageQueue}. 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 thatpoint on, it will deliver messages and

 * runnablesto that message queue and execute them as they come out of the

 *message queue.

 *

 *There are two main uses for a Handler: (1) to schedule messages and runnables

 * tobe executed as some point in the future; and (2) to enqueue an action to

 * beperformed on a different thread than your own.

 *

 *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 post versions allow you

 * toenqueue Runnable objects to be called by the message queue when they are

 *received; the sendMessage versions allow you to enqueue a

 * {@link Message} object containing a bundle of data thatwill be processed by

 *the Handler's {@link #handleMessage} method (requiring that you implement a

 *subclass of Handler).

 *

 *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.

 *

 *When a process is created for your application, its main thread is dedicated

 * torunning 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

 *post or sendMessage 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允许你去发送和处理Message和Runnable对象,

 * 而Message和Runnable对象是与一个线程的MessageQueue相关的。

 * 每个Handler实例与一个单独的线程相关且和这个线程的MessageQueue相关。

 * 当你创建一个Handler的时候,这个Handler会绑定到创建这个Handler的线程和线程的MessageQueue。

 * 从创建Handler开始,Handler将会发送Message 和Runnable到对应的MessageQueue,

 * 并且在Message和Runnable被移出MessageQueue的时候处理。

 *

 *Handler有两个主要用法:

 * (1)计划在将来的某个时间点处理Message和Runnable。

 * (2)在不同的线程里将一个动作加入Handler所对应的队列去执行,这个线程不只是创建Handler的线程。

 *

 * 计划Message用以下这些方法来完成,#post,#postAtTime(Runnable,long),

 *#postDelayed,#sendEmptyMessage,#sendMessage,

 *#sendMessageAtTime,#sendMessageDelayed

 * 这个post版本的方法允许你把Runnable对象加入队列,在Runnable对象移出的时候被MessageQueue调用;

 * 这个sendMessage版本的方法允许你把Message对象(Message对象里包含一些数据)加入队列,

 * 并且被Handler的#handleMessage方法处理,

 * 这个sendMessage版本需要你实现Handler的子类,重写#handleMessage方法。

 *

 * 当posting或 sending

 * 给Handler时,你能允许这item在MessageQueue准备好后及时的被处理或者指定一个延迟时间,

 * 又或者指定一个绝对时间点。

 *#sendMessageAtTime,#sendMessageDelayed这两个方法允许你实现延时,定时,和其它基于定时的操作。

 *

 * 当你的应用进程被创建的时候,应用的主线程就一直致力于运行一个MessageQueue

 * 主线程致力于管理顶级应用对象(activity,broadcast receivers,etc)和任何创建的窗口。

 * 你可以创建你自己的线程,然后通过Handler与应用主线程通信。这种与主线程的通信方式被实现,

 * 也是像之前一样同样通过post和sendMessage方法。

 *Runnable对象和Message将要被加入Handler的MessageQueue中,在合适的时候被处理。

 */

public class Handler {

    /**

     * Set this flag to true to detect anonymous,local or member classes that

     * extend this Handler class and that are notstatic. These kind of classes

     * can potentially create leaks.

     *

     * 设置这个flag为true来检测继承Handler类并且非静态的匿名、本地、成员类。

     * 这一类型的类会潜在的产生泄露。

     */

    private static final boolean FIND_POTENTIAL_LEAKS =false;

    private static final String TAG ="Handler";

 

    /**

     * Callback interface you can use wheninstantiating a Handler to avoid

     * having to implement your own subclass ofHandler.

     *

     * @param msg

     *           A {@link android.os.Message Message} object

     * @return True if no further handling is desired

     *

     * 在实例化一个Handler的时候你可以使用这个回调接口,这样就可以避免实现你自己的Handler子类

     * 在使用Handler的时候通常会重写Handler类的#handleMessage方法,

     * 而重写这个方法无非就是继承Handler重写该方法

     * 或者创建的时候重写该方法

     *

     * 如果Callback#handleMessage方法返回false,

     * 那么Handler还会执行Handler#handleMessage方法

     * 否则只执行Callback#handleMessage方法

     */

    public interfaceCallback {

       public booleanhandleMessage(Message msg);

    }

 

    /**

     * Subclasses must implement this to receivemessages.

     *

     * 子类必须实现这个方法来接受消息

     */

    public voidhandleMessage(Message msg) {

    }

 

    /**

     * Handle system messages here.

     *

     * 这个地方负责分发处理Message

     *

     * 处理过程分析:

     * 1.判断Message是否有callback(msg.callback是Runnable对象的引用),

     * 有则执行Runnable代码且分发Message结束,否则执行第2步。

     * 2.判断Handler#mCallback成员变量是否为null,为null执行第3步,

     * 不为null执行mCallback#handleMessage,该方法有返回值,

     * 返回true分发结束,返回false则还会执行第3步。

     * 3.执行Handler#handleMessage

     *

     */

    public voiddispatchMessage(Message msg) {

       if (msg.callback !=null) {           //这部分用来处理Handler#post方法

           handleCallback(msg);

       }else {

           if (mCallback!=null){           //这部分用来处理Handler#Callback接口,如果使用

              if (mCallback.handleMessage(msg)){

                  return;

              }

           }

           handleMessage(msg);

       }

    }

 

    /**

     * Default constructor associates this handlerwith the{@link Looper} for

     * the current thread.

     *

     * If this thread does not have a looper, thishandler won't be able to

     * receive messages so an exception is thrown.

     *

     * 默认构造方法,把Handler和当前线程的Looper联系起来

     * 如果这个线程没有Looper,这个Handler将不会接收到Message,

     * 并且会抛出一个exception

     */

    public Handler() {

       this(null,false);//Handler(Callback callback, boolean async)

    }

 

    /**

     * Constructor associates this handler with the{@link Looper} for the

     * current thread and takes a callbackinterface in which you can handle

     * messages.

     *

     * If this thread does not have a looper, thishandler won't be able to

     * receive messages so an exception is thrown.

     *

     * @param callback

     *           The callback interface in which to handle messages, or null.

     *           

     * callback Callback接口,接口里去处理Message,或者为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.

     *           

     * 使用提供的Looper替代默认的Looper,默认是当前线程的Looper

     * 参数looper不能为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 handlemessages.

     *

     * @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 thehandler

     * should be asynchronous.

     *

     * Handlers are synchronous by default unlessthis constructor is used to

     * make one that is strictly asynchronous.

     *

     * Asynchronous messages represent interruptsor events that do not require

     * global ordering with represent tosynchronous messages. Asynchronous

     * messages are not subject to thesynchronization barriers introduced by

     * {@linkMessageQueue#enqueueSyncBarrier(long)}.

     *

     * @param async

     *           If true, the handler calls

     *           {@link Message#setAsynchronous(boolean)} for each

     *           {@link Message} that is sent to it or{@linkRunnable} that is

     *           posted to it.

     *

     * @hide

     */

    //异步Message暂时不用到

    public Handler(boolean async) {

       this(null,async);

    }

 

    /**

     * Use the {@link Looper} for the current thread with the specifiedcallback

     * interface and set whether the handler shouldbe asynchronous.

     *

     * Handlers are synchronous by default unlessthis constructor is used to

     * make one that is strictly asynchronous.

     *

     * Asynchronous messages represent interruptsor events that do not require

     * global ordering with represent tosynchronous messages. Asynchronous

     * messages are not subject to thesynchronization barriers introduced by

     * {@linkMessageQueue#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 newRuntimeException(

                  "Can't create handler inside thread that has not calledLooper.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 handlemessages. Also set whether the

     * handler should be asynchronous.

     *

     * Handlers are synchronous by default unlessthis constructor is used to

     * make one that is strictly asynchronous.

     *

     * Asynchronous messages represent interruptsor events that do not require

     * global ordering with represent tosynchronous messages. Asynchronous

     * messages are not subject to thesynchronization barriers introduced by

     * {@linkMessageQueue#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{@linkRunnable} that is

     *           posted to it.

     *

     * @hide

     */

    //异步Message暂时不用到

    public Handler(Looper looper, Callback callback,boolean async) {

       mLooper = looper;

       mQueue = looper.mQueue;

       mCallback = callback;

       mAsynchronous = async;

    }

 

    /**

     * Returns a string representing the name ofthe specified message. The

     * default implementation will either returnthe class name of the message

     * callback if any, or the hexadecimalrepresentation of the message "what"

     * field.

     *

     * @param message

     *           The message whose name is being queried

     *           

     * 返回一个字符串代表指定Message的名字。

     * 默认实现是返回Message里callback(Runnable)的类名如果有的话,

     * 或者返回一个十六进制数字的字符串,这个字符串表示的是Message#what域的值。

     */

    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 andallocating new instances. The

     * retrieved message has its handler set tothis instance (Message.target ==

     * this). If you don't want that facility, justcall Message.obtain()

     * instead.

     *

     * 返回一个新的Message,返回的Message都是从全局Message池里获取的。

     * 这样做更有效率比创建和开辟新的实例。

     * 这个或取的Message对象有它自己的Handler,(Message.target == this)。

     * 如果你不想这样做,可以调用Message.obtain()来替代。

     * Message全局消息池里Message的数量由Message#MAX_POOL_SIZE来表示,默认为50个。

     */

    public finalMessage obtainMessage() {

        returnMessage.obtain(this);

    }

 

    /**

     * Same as {@link #obtainMessage()}, except thatit 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.

     *

     * 返回一个Message实例并且设置了what域和target域的值

     */

    public finalMessage obtainMessage(intwhat) {

       return Message.obtain(this, what);

    }

 

    /**

     *

     * Same as {@link #obtainMessage()}, except thatit 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.

     *

     * 返回一个Message实例并且设置了what域的值和obj域的值

     */

    public finalMessage obtainMessage(intwhat, Object obj) {

       return Message.obtain(this, what, obj);

    }

 

    /**

     *

     * Same as {@link #obtainMessage()}, except thatit 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.

     *

     * 返回一个Message实例并且设置了what域arg1域和arg2域的值

     */

    public finalMessage obtainMessage(intwhat,intarg1, intarg2) {

       return Message.obtain(this, what, arg1, arg2);

    }

 

    /**

     *

     * Same as {@link #obtainMessage()}, except thatit also sets the what, obj,

     * arg1,and arg2 values on the returnedMessage.

     *

     * @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.

     *

     * 返回一个Message实例并且设置了what域arg1域arg2域和obj域的值

     */

    public finalMessage obtainMessage(intwhat,intarg1, intarg2, Object obj) {

       return Message.obtain(this, what, arg1, arg2, obj);

    }

 

    /**

     * Causes the Runnable r to be added to themessage queue. The runnable will

     * be run on the thread to which this handleris 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立刻加入MessageQueue。这个Runnable将要在Handler所在的线程上执行。

     * 返回true表示Runnable被成功加入到MessageQueue。返回false表示加入失败(判断加入失败就是先判断mQueue是否为null),

     * 通常处理MessageQueue的Looper是存在的。

     *

     * 原理就是获取一个新的Message,然后将Runnable赋值给Message的callback域,

     * 在Message分发的时候就优先处理了

     */

    public final boolean post(Runnable r) {

       return sendMessageDelayed(getPostMessage(r),0);

    }

 

    /**

     * Causes the Runnable r to be added to themessage queue, to be run at a

     * specific time given by <var>uptimeMillis</var>.<b>The time-base is

     * {@linkandroid.os.SystemClock#uptimeMillis}.</b> The runnable will be run

     * on the thread to which this handler isattached.

     *

     * @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在指定时间加入MessageQueue。

     */

    public final boolean postAtTime(Runnable r,long uptimeMillis) {

       return sendMessageAtTime(getPostMessage(r),uptimeMillis);

    }

 

    /**

     * Causes the Runnable r to be added to themessage queue, to be run at a

     * specific time given by <var>uptimeMillis</var>.<b>The time-base is

     * {@linkandroid.os.SystemClock#uptimeMillis}.</b> The runnable will be run

     * on the thread to which this handler isattached.

     *

     * @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

     *

     * 将Runnable在指定时间加入MessageQueue,并且还设置了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 themessage queue, to be run after

     * the specified amount of time elapses. Therunnable 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.

     *        

     * 将Runnable延时加入MessageQueue。

     */

    public final boolean postDelayed(Runnable r,long delayMillis) {

       return sendMessageDelayed(getPostMessage(r),delayMillis);

    }

 

    /**

     * Posts a message to an object that implementsRunnable. Causes the

     * Runnable r to executed on the next iterationthrough the message queue.

     * The runnable will be run on the thread towhich this handler is attached.

     * <b>This method is only for use in very special circumstances-- it can

     * easily starve the message queue, causeordering 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插入到最前面,下一个就执行;

     * 这个方法只用于非常紧急的情况,该方法可能很容易造成顺序问题,

     * 阻碍其他message执行,或引起其他不希望的影响

     */

    public final boolean postAtFrontOfQueue(Runnable r) {

       return sendMessageAtFrontOfQueue(getPostMessage(r));

    }

 

    /**

     * Runs the specified task synchronously.

     * <p>

     * If the current thread is the same as thehandler thread, then the

     * runnable runs immediately without beingenqueued. Otherwise, posts the

     * runnable to the handler and waits for it tocomplete before returning.

     * </p>

     * <p>

     * This method is dangerous! Improper use canresult in deadlocks. Never

     * call this method while any locks are held oruse it in a possibly

     * re-entrant manner.

     * </p>

     * <p>

     * This method is occasionally useful insituations where a background

     * thread must synchronously await completionof a task that must run on the

     * handler's thread. However, this problem isoften 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 usethis method is when you just

     * set up a Handler thread and need to performsome 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 handlerand 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 MessageQueueaware 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 newIllegalArgumentException("runnablemust not be null");

       }

       if (timeout < 0) {

           throw newIllegalArgumentException("timeoutmust be non-negative");

       }

 

       if (Looper.myLooper() ==mLooper) {

           r.run();

           return true;

       }

 

       BlockingRunnablebr = newBlockingRunnable(r);

       return br.postAndWait(this, timeout);

    }

 

    /**

     * Remove any pending posts of Runnable r thatare in the message queue.

     *

     * 移除所有挂起的 r对象。

     */

    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.

     *

     * 移除所有挂起的拥有token的 r 对象,如果token为null,移除所有的挂起的 r 对象。

     */

    public final void removeCallbacks(Runnable r, Object token) {

       mQueue.removeMessages(this, r, token);

    }

    /**

     * Pushes a message onto the end of the messagequeue after all pending

     * messages before the current time. It will bereceived 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.

     *

     * 立即发送一条message

     */

    public final boolean sendMessage(Message msg) {

       return sendMessageDelayed(msg, 0);

    }

 

    /**

     * Sends a Message containing only the whatvalue.

     *

     * @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.

     *        

     * 发送的message只包含what域

     */

    public final boolean sendEmptyMessage(int what) {

       return sendEmptyMessageDelayed(what, 0);

    }

 

    /**

     * Sends a Message containing only the whatvalue, 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.

     *        

     * 延迟发送一条message,该message只包含what域

     */

    public final boolean sendEmptyMessageDelayed(int what,long delayMillis) {

       Messagemsg = Message.obtain();

       msg.what = what;

       return sendMessageDelayed(msg, delayMillis);

    }

 

    /**

     * Sends a Message containing only the whatvalue, 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) {

       Messagemsg = Message.obtain();

       msg.what = what;

       return sendMessageAtTime(msg, uptimeMillis);

    }

 

    /**

     * Enqueue a message into the message queueafter all pending messages

     * before (current time + delayMillis). Youwill 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.

     *        

     * 延时发送message

     */

    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 queueafter all pending messages

     * before the absolute time (in milliseconds)<var>uptimeMillis</var>.

     * <b>The time-base is{@link android.os.SystemClock#uptimeMillis}.</b> You

     * will receive it in {@link #handleMessage}, in thethread 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.

     *        

     * 定时间点发送message

     */

    public booleansendMessageAtTime(Message msg, longuptimeMillis) {

       MessageQueuequeue = mQueue;

       if (queue ==null) {

           RuntimeExceptione = newRuntimeException(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 themessage queue, to be processed on

     * the next iteration of the message loop. Youwill receive it in

     * {@link#handleMessage}, in the thread attached to this handler.<b>This

     * method is only for use in very specialcircumstances-- it caneasily

     * starve the message queue, cause orderingproblems, 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) {

       MessageQueuequeue = mQueue;

       if (queue ==null) {

           RuntimeExceptione = newRuntimeException(this

                  +" sendMessageAtTime() called with no mQueue");

           Log.w("Looper",e.getMessage(), e);

           return false;

       }

       return enqueueMessage(queue, msg, 0);

    }

 

    // / M: MSG Logger Manager @{

    /**

     * @hide

     */

    public final void sendMonitorMessage(Message msg,long delayMillis,

           long executiontimeout,long pendingtimeout, String msgLoggerName) {

       if (null != MessageMonitorLogger.mMsgLoggerHandler) {

           MessageMonitorLogger.MonitorMSGInfomsgMonitorInfo = new MessageMonitorLogger.MonitorMSGInfo();

           msgMonitorInfo.msg= msg;

           msgMonitorInfo.msgLoggerName= msgLoggerName;

           msgMonitorInfo.executionTimeout= executiontimeout;

           MessageMonitorLogger.monitorMsg.put(msg,msgMonitorInfo);

 

           try {

              if (pendingtimeout > 100) {

                  Messagemsg1 = MessageMonitorLogger.mMsgLoggerHandler

                         .obtainMessage(

                                MessageMonitorLogger.START_MONITOR_PENDING_TIMEOUT_MSG,

                                msgMonitorInfo);

                  MessageMonitorLogger.mMsgLoggerHandler.sendMessageDelayed(

                         msg1,delayMillis + pendingtimeout);

              }else {

                  if (pendingtimeout != MessageMonitorLogger.DISABLE_MONITOR_PENDING_TIMEOUT_MSG)

                     thrownewIllegalArgumentException(

                            "Pendingtimeout <100 ms!");

              }

           }catch (Exception e){

              Log.d("Handler","Pending timeout exception "+ e);

           }

       }else {

           Log.d("Handler","You didn't register message logger");

       }

       sendMessageDelayed(msg,delayMillis);

    }

 

    /**

     * @hide

     */

    public final void removeMonitorMessage(int what) {

       Iteratoriter = MessageMonitorLogger.monitorMsg.keySet().iterator();

       while (iter.hasNext()) {

           Messagemsg = (Message) iter.next();

           if (msg.what == what) {

              MessageMonitorLogger.MonitorMSGInfomonitorMsg = MessageMonitorLogger.monitorMsg

                     .get(msg);

              if (MessageMonitorLogger.mMsgLoggerHandler.hasMessages(

                     MessageMonitorLogger.START_MONITOR_PENDING_TIMEOUT_MSG,

                     monitorMsg)){

                  Log.d("Looper","Remove monitor msg= " + msg);

                  MessageMonitorLogger.mMsgLoggerHandler

                         .removeMessages(

                                MessageMonitorLogger.START_MONITOR_PENDING_TIMEOUT_MSG,

                                monitorMsg);

                  MessageMonitorLogger.monitorMsg.remove(msg);

              }

           }

       }

       mQueue.removeMessages(this, what,null);

    }

 

    /**

     * @hide

     */

    public final void removeMonitorMessage(int what, Object object) {

       Iteratoriter = MessageMonitorLogger.monitorMsg.keySet().iterator();

       while (iter.hasNext()) {

           Messagemsg = (Message) iter.next();

           if (msg.what == what && msg.obj == object) {

              MessageMonitorLogger.MonitorMSGInfomonitorMsg = MessageMonitorLogger.monitorMsg

                     .get(msg);

              if (MessageMonitorLogger.mMsgLoggerHandler.hasMessages(

                     MessageMonitorLogger.START_MONITOR_PENDING_TIMEOUT_MSG,

                     monitorMsg)){

                  Log.d("Looper","Remove monitor msg= " + msg);

                  MessageMonitorLogger.mMsgLoggerHandler

                         .removeMessages(

                                MessageMonitorLogger.START_MONITOR_PENDING_TIMEOUT_MSG,

                                monitorMsg);

                  MessageMonitorLogger.monitorMsg.remove(msg);

              }

           }

       }

       mQueue.removeMessages(this, what, object);

    }

 

    // / MSG Logger Manager @}

 

    /**

     * 将message加入到队列

     */

    private booleanenqueueMessage(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 withcode '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 withcode 'what' and whose obj is

     * 'object' that are in the message queue. If<var>object</var> is null, all

     * messages will be removed.

     *

     * 同上,增加了object筛选

     */

    public final void removeMessages(int what, Object object) {

       mQueue.removeMessages(this, what, object);

    }

 

    /**

     * Remove any pending posts of callbacks andsent 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 ofmessages with code 'what' in the

     * message queue.

     *

     * 判断是否有what标识的message在队列里

     */

    public final boolean hasMessages(int what) {

       returnmQueue.hasMessages(this, what,null);

    }

 

    /**

     * Check if there are any pending posts ofmessages with code 'what' and

     * whose obj is 'object' in the message queue.

     *

     * 同上,增加object

     */

    public final boolean hasMessages(int what, Object object) {

       returnmQueue.hasMessages(this, what, object);

    }

 

    /**

     * Check if there are any pending posts ofmessages with callback r in the

     * message queue.

     *

     * @hide

     *

     * 判断队列里是否还有r

     */

    public final boolean hasCallbacks(Runnable r) {

       returnmQueue.hasMessages(this, r,null);

    }

 

    // if we can get rid of this method, the handler need not remember itsloop

    // we could instead export a getMessageQueue() method...

    public finalLooper getLooper() {

       returnmLooper;

    }

 

    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){

              returnmMessenger;

           }

           mMessenger = new MessengerImpl();

           returnmMessenger;

       }

    }

 

    private final class MessengerImpl extends IMessenger.Stub {

       public voidsend(Message msg) {

           Handler.this.sendMessage(msg);

       }

    }

 

    private staticMessage getPostMessage(Runnable r) {

       Messagem = Message.obtain();

       m.callback = r;

       return m;

    }

 

    private staticMessage getPostMessage(Runnable r, Object token) {

       Messagem = Message.obtain();

       m.obj = token;

       m.callback = r;

       return m;

    }

 

    private static void handleCallback(Message message) {

       message.callback.run();

    }

 

    final MessageQueuemQueue;

    final LoopermLooper;

    final CallbackmCallback;

    final boolean mAsynchronous;

    IMessengermMessenger;

 

    private static final classBlockingRunnable implementsRunnable {

       private finalRunnable mTask;

       private boolean mDone;

 

       public BlockingRunnable(Runnable task) {

           mTask = task;

       }

 

       @Override

       public voidrun() {

           try {

              mTask.run();

           }finally {

              synchronized (this) {

                  mDone = true;

                  notifyAll();

              }

           }

       }

 

       public booleanpostAndWait(Handler handler, longtimeout) {

           if (!handler.post(this)) {

              return false;

           }

 

           synchronized (this) {

              if (timeout > 0) {

                  finallongexpirationTime = SystemClock.uptimeMillis()

                         +timeout;

                  while (!mDone){

                     long delay = expirationTime

                            -SystemClock.uptimeMillis();

                     if (delay <= 0) {

                         returnfalse;// timeout

                     }

                     try {

                         wait(delay);

                     }catch(InterruptedException ex) {

                     }

                  }

              }else {

                  while (!mDone){

                     try {

                         wait();

                     }catch(InterruptedException ex) {

                     }

                  }

              }

           }

           return true;

       }

    }

}

 


0 0
原创粉丝点击