android源码解析--Handler

Handler是用于发送和处理消息和一个线程的MessageQueue相关联的Runable对象。每个Handler实例关联到一个单一线程和线程的messagequeue。当您创建一个Handler,从你创建它的时候开始,它就绑定到创建它的线程以及对应的消息队列,handler将发送消息到消息队列,并处理从消息队列中取出的消息。

Handler的主要用途有两个:(1)、在将来的某个时刻执行消息或一个runnable,(2)、为运行在不同线程中的多个任务排队。

   主要依靠post(Runnable)、postAtTime(Runnable, long)、postDelayed(Runnable, long)、sendEmptyMessage(int)、sendMessage(Message)、sendMessageAtTi(Message)、sendMessageDelayed(Message, long)这些方法来来完成消息调度。post方法是当到Runable对象到达就被插入到消息队列;sendMessage方法允许你把一个包含有信息的Message插入队列,而且它会Handler的handlerMessage(Message)方法中执行(该方法要求在Handler的子类中实现)。

当向Handler post或者send消息的时候,你可以在消息队列准备好的时候立刻执行,或者指定一个延迟之前得到处理或绝对时间对它进行处理,后两个是实现了timeout、ticks或者其他timing-based的行为。

当你的应用创建一个进程时,其主线程(UI线程)会运行一个消息队列,负责管理优先级最高的应用程序对象(活动、广播接收器等)和任何他们创建的windows。你也可以创建自己的线程,通过handler与主线程进行通信,通过在你创建的线程调用的post或sendMessage方法。传入的Runnable或者消息会被插入到消息队列并且在适当的时候得到处理。

 

先看下类里面使用的全局变量:

 

[java]  view plain copy
  1. final MessageQueue mQueue;  
  2.     final Looper mLooper;  
  3.     final Callback mCallback;  
  4.     IMessenger mMessenger;  

都会在构造方法里面赋值:

 

 

[java]  view plain copy
  1.   /** 
  2.      * Default constructor associates this handler with the queue for the 
  3.      * current thread. 
  4.      * 
  5.      * If there isn't one, this handler won't be able to receive messages. 
  6.      */  
  7.     public Handler() {  
  8.         if (FIND_POTENTIAL_LEAKS) {  
  9.             final Class<? extends Handler> klass = getClass();  
  10.             if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&  
  11.                     (klass.getModifiers() & Modifier.STATIC) == 0) {  
  12.                 Log.w(TAG, "The following Handler class should be static or leaks might occur: " +  
  13.                     klass.getCanonicalName());  
  14.             }  
  15.         }  
  16.   
  17.   
  18.         mLooper = Looper.myLooper();  
  19.         if (mLooper == null) {  
  20.             throw new RuntimeException(  
  21.                 "Can't create handler inside thread that has not called Looper.prepare()");  
  22.         }  
  23.         mQueue = mLooper.mQueue;  
  24.         mCallback = null;  
  25.     }  
  26.   
  27.   
  28.     /** 
  29.      * Constructor associates this handler with the queue for the 
  30.      * current thread and takes a callback interface in which you can handle 
  31.      * messages. 
  32.      */  
  33.     public Handler(Callback callback) {  
  34.         if (FIND_POTENTIAL_LEAKS) {  
  35.             final Class<? extends Handler> klass = getClass();  
  36.             if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&  
  37.                     (klass.getModifiers() & Modifier.STATIC) == 0) {  
  38.                 Log.w(TAG, "The following Handler class should be static or leaks might occur: " +  
  39.                     klass.getCanonicalName());  
  40.             }  
  41.         }  
  42.   
  43.   
  44.         mLooper = Looper.myLooper();  
  45.         if (mLooper == null) {  
  46.             throw new RuntimeException(  
  47.                 "Can't create handler inside thread that has not called Looper.prepare()");  
  48.         }  
  49.         mQueue = mLooper.mQueue;  
  50.         mCallback = callback;  
  51.     }  
  52.   
  53.   
  54.     /** 
  55.      * Use the provided queue instead of the default one. 
  56.      */  
  57.     public Handler(Looper looper) {  
  58.         mLooper = looper;  
  59.         mQueue = looper.mQueue;  
  60.         mCallback = null;  
  61.     }  
  62.   
  63.   
  64.     /** 
  65.      * Use the provided queue instead of the default one and take a callback 
  66.      * interface in which to handle messages. 
  67.      */  
  68.     public Handler(Looper looper, Callback callback) {  
  69.         mLooper = looper;  
  70.         mQueue = looper.mQueue;  
  71.         mCallback = callback;  
  72.     }  

在默认构造方法里面,handler是和当前线程的队列关联在一起,如果队列不存在,那么handler就不能接受消息。第二个有参构造方法中,需要传入一个callback接口用于处理handler传递的Message。第三个有参构造函数是传进来一个looper来代替默认的looper。第四个就是传递一个looper和callback。

 

在70行有个 FIND_POTENTIAL_LEAKS参数:找到潜在的泄露。看下注释:

 

[plain]  view plain copy
  1. /*  
  2.      * Set this flag to true to detect anonymous, local or member classes  
  3.      * that extend this Handler class and that are not static. These kind  
  4.      * of classes can potentially create leaks.  
  5.      */  

 

设置这个标记为true来检测不是静态的匿名,本地或成员类继承Handler类。这些类型的类可以带来潜在的泄漏。在Handler的构造方法里面使用到了这个参数,目的就如上所述:

 

[java]  view plain copy
  1. if (FIND_POTENTIAL_LEAKS) {  
  2.             final Class<? extends Handler> klass = getClass();  
  3.             if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&  
  4.                     (klass.getModifiers() & Modifier.STATIC) == 0) {  
  5.                 Log.w(TAG, "The following Handler class should be static or leaks might occur: " +  
  6.                     klass.getCanonicalName());  
  7.             }  
  8.         }  

 

接着下面就是Callback接口:

 

[java]  view plain copy
  1. /** 
  2.      * Callback interface you can use when instantiating a Handler to avoid 
  3.      * having to implement your own subclass of Handler. 
  4.      */  
  5.     public interface Callback {  
  6.         public boolean handleMessage(Message msg);  
  7.     }  

 

当你实例化一个Handler的时候可以使用Callback接口来避免写自定义的Handler子类。这里的机制类似与Thread与runable接口的关系。

在Handler里面,子类要处理消息的话必须重写handleMessage()这个方法,因为在handler里面它是个空方法:

 

[java]  view plain copy
  1. /** 
  2.      * Subclasses must implement this to receive messages. 
  3.      */  
  4.     public void handleMessage(Message msg) {  
  5.     }  


再来看一下:dispatchMessage()这个方法:

[java]  view plain copy
  1. /** 
  2.      * Handle system messages here. 
  3.      */  
  4.     public void dispatchMessage(Message msg) {  
  5.         if (msg.callback != null) {  
  6.             handleCallback(msg);  
  7.         } else {  
  8.             if (mCallback != null) {  
  9.                 if (mCallback.handleMessage(msg)) {  
  10.                     return;  
  11.                 }  
  12.             }  
  13.             handleMessage(msg);  
  14.         }  
  15.     }  

用于传递系统消息。当message的callback不为空的时候,调用handleCallback方法,如下:

 

 

[java]  view plain copy
  1. private final void handleCallback(Message message) {  
  2.         message.callback.run();  
  3.     }  

关于调用Message的方法,在这篇文章里面先不谈,解析Message源码的时候再说。

下面是171行的getMessageName()方法:

 

[java]  view plain copy
  1. <span style="font-size:14px;">/** 
  2.      * Returns a string representing the name of the specified message. 
  3.      * The default implementation will either return the class name of the 
  4.      * message callback if any, or the hexadecimal representation of the 
  5.      * message "what" field. 
  6.      *   
  7.      * @param message The message whose name is being queried  
  8.      */  
  9.     public String getMessageName(Message message) {  
  10.         if (message.callback != null) {  
  11.             return message.callback.getClass().getName();  
  12.         }  
  13.         return "0x" + Integer.toHexString(message.what);  
  14.     }</span>  


我们从源码中结合注释,返回传入message的name值,默认的实现是如火message.callback不为空,就返回callback的类名,或者返回一个16进制的message的what值。

 

再往下,191行的obtainMessage()方法:

[java]  view plain copy
  1. <span style="font-size:14px;">  /** 
  2.      * Returns a new {@link android.os.Message Message} from the global message pool. More efficient than 
  3.      * creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this). 
  4.      *  If you don't want that facility, just call Message.obtain() instead. 
  5.      */  
  6.     public final Message obtainMessage()  
  7.     {  
  8.         return Message.obtain(this);  
  9.     }</span>  


从一个全局消息池里面获取一个新的Message。在Message池中检索是否存在与handler实例对应的message比创建一个新的Message更高效。如果你不想创建新Message,就是用Message.obtain方法代替。

 

下面是几个obtainMessage的重载方法:

 

[java]  view plain copy
  1. <span style="font-size:14px;">    /** 
  2.      *  
  3.      * Same as {@link #obtainMessage()}, except that it also sets the what and obj members  
  4.      * of the returned Message. 
  5.      *  
  6.      * @param what Value to assign to the returned Message.what field. 
  7.      * @param obj Value to assign to the returned Message.obj field. 
  8.      * @return A Message from the global message pool. 
  9.      */  
  10.     public final Message obtainMessage(int what, Object obj)  
  11.     {  
  12.         return Message.obtain(this, what, obj);  
  13.     }  
  14.   
  15.     /** 
  16.      *  
  17.      * Same as {@link #obtainMessage()}, except that it also sets the what, arg1 and arg2 members of the returned 
  18.      * Message. 
  19.      * @param what Value to assign to the returned Message.what field. 
  20.      * @param arg1 Value to assign to the returned Message.arg1 field. 
  21.      * @param arg2 Value to assign to the returned Message.arg2 field. 
  22.      * @return A Message from the global message pool. 
  23.      */  
  24.     public final Message obtainMessage(int what, int arg1, int arg2)  
  25.     {  
  26.         return Message.obtain(this, what, arg1, arg2);  
  27.     }  
  28.       
  29.     /** 
  30.      *  
  31.      * Same as {@link #obtainMessage()}, except that it also sets the what, obj, arg1,and arg2 values on the  
  32.      * returned Message. 
  33.      * @param what Value to assign to the returned Message.what field. 
  34.      * @param arg1 Value to assign to the returned Message.arg1 field. 
  35.      * @param arg2 Value to assign to the returned Message.arg2 field. 
  36.      * @param obj Value to assign to the returned Message.obj field. 
  37.      * @return A Message from the global message pool. 
  38.      */  
  39.     public final Message obtainMessage(int what, int arg1, int arg2, Object obj)  
  40.     {  
  41.         return Message.obtain(this, what, arg1, arg2, obj);  
  42.     }</span>  


和上面相同,只是参数不同,为返回的Message的一些属性赋值。

 

在往下就是post()方法了:

[java]  view plain copy
  1. <span style="font-size:14px;">/** 
  2.      * Causes the Runnable r to be added to the message queue. 
  3.      * The runnable will be run on the thread to which this handler is  
  4.      * attached.  
  5.      *   
  6.      * @param r The Runnable that will be executed. 
  7.      *  
  8.      * @return Returns true if the Runnable was successfully placed in to the  
  9.      *         message queue.  Returns false on failure, usually because the 
  10.      *         looper processing the message queue is exiting. 
  11.      */  
  12.     public final boolean post(Runnable r)  
  13.     {  
  14.        return  sendMessageDelayed(getPostMessage(r), 0);  
  15.     }</span>  


把传入的Runnable对象r加入到Message队列中,这个runnable对象将在handler关联的线程中执行。如果runnable对象被正确执行返回true,如果looper遍历消息队列时退出,则返回false。在这个方法中,主要是调用了sendMessageDelayed方法。在下面会有相应的分析。

 

接下来,看一下其他有关post的方法(从266行到353行):

 

[java]  view plain copy
  1. <span style="font-size:14px;">   /** 
  2.      * Causes the Runnable r to be added to the message queue, to be run 
  3.      * at a specific time given by <var>uptimeMillis</var>. 
  4.      * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b> 
  5.      * The runnable will be run on the thread to which this handler is attached. 
  6.      * 
  7.      * @param r The Runnable that will be executed. 
  8.      * @param uptimeMillis The absolute time at which the callback should run, 
  9.      *         using the {@link android.os.SystemClock#uptimeMillis} time-base. 
  10.      *   
  11.      * @return Returns true if the Runnable was successfully placed in to the  
  12.      *         message queue.  Returns false on failure, usually because the 
  13.      *         looper processing the message queue is exiting.  Note that a 
  14.      *         result of true does not mean the Runnable will be processed -- if 
  15.      *         the looper is quit before the delivery time of the message 
  16.      *         occurs then the message will be dropped. 
  17.      */  
  18.     public final boolean postAtTime(Runnable r, long uptimeMillis)  
  19.     {  
  20.         return sendMessageAtTime(getPostMessage(r), uptimeMillis);  
  21.     }  
  22.       
  23.     /** 
  24.      * Causes the Runnable r to be added to the message queue, to be run 
  25.      * at a specific time given by <var>uptimeMillis</var>. 
  26.      * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b> 
  27.      * The runnable will be run on the thread to which this handler is attached. 
  28.      * 
  29.      * @param r The Runnable that will be executed. 
  30.      * @param uptimeMillis The absolute time at which the callback should run, 
  31.      *         using the {@link android.os.SystemClock#uptimeMillis} time-base. 
  32.      *  
  33.      * @return Returns true if the Runnable was successfully placed in to the  
  34.      *         message queue.  Returns false on failure, usually because the 
  35.      *         looper processing the message queue is exiting.  Note that a 
  36.      *         result of true does not mean the Runnable will be processed -- if 
  37.      *         the looper is quit before the delivery time of the message 
  38.      *         occurs then the message will be dropped. 
  39.      *          
  40.      * @see android.os.SystemClock#uptimeMillis 
  41.      */  
  42.     public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)  
  43.     {  
  44.         return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);  
  45.     }  
  46.       
  47.     /** 
  48.      * Causes the Runnable r to be added to the message queue, to be run 
  49.      * after the specified amount of time elapses. 
  50.      * The runnable will be run on the thread to which this handler 
  51.      * is attached. 
  52.      *   
  53.      * @param r The Runnable that will be executed. 
  54.      * @param delayMillis The delay (in milliseconds) until the Runnable 
  55.      *        will be executed. 
  56.      *         
  57.      * @return Returns true if the Runnable was successfully placed in to the  
  58.      *         message queue.  Returns false on failure, usually because the 
  59.      *         looper processing the message queue is exiting.  Note that a 
  60.      *         result of true does not mean the Runnable will be processed -- 
  61.      *         if the looper is quit before the delivery time of the message 
  62.      *         occurs then the message will be dropped. 
  63.      */  
  64.     public final boolean postDelayed(Runnable r, long delayMillis)  
  65.     {  
  66.         return sendMessageDelayed(getPostMessage(r), delayMillis);  
  67.     }  
  68.       
  69.     /** 
  70.      * Posts a message to an object that implements Runnable. 
  71.      * Causes the Runnable r to executed on the next iteration through the 
  72.      * message queue. The runnable will be run on the thread to which this 
  73.      * handler is attached. 
  74.      * <b>This method is only for use in very special circumstances -- it 
  75.      * can easily starve the message queue, cause ordering problems, or have 
  76.      * other unexpected side-effects.</b> 
  77.      *   
  78.      * @param r The Runnable that will be executed. 
  79.      *  
  80.      * @return Returns true if the message was successfully placed in to the  
  81.      *         message queue.  Returns false on failure, usually because the 
  82.      *         looper processing the message queue is exiting. 
  83.      */  
  84.     public final boolean postAtFrontOfQueue(Runnable r)  
  85.     {  
  86.         return sendMessageAtFrontOfQueue(getPostMessage(r));  
  87.     }  
  88. </span>  


postAtTime在指定时间uptimeMillis把runnable插入到队列中去,另一个postAtTime方法又加了一个Object类型的token,在下面的sendMessageAtTime中具体分析。postDelayed在延迟delayMillis时间后插入队列。postAtFrontOfQueue把Runnable插入到队首,下一次轮询就会被执行。

 

下面是从队列中删除对应的runable:

 

[java]  view plain copy
  1. <span style="font-size:14px;">    /** 
  2.      * Remove any pending posts of Runnable r that are in the message queue. 
  3.      */  
  4.     public final void removeCallbacks(Runnable r)  
  5.     {  
  6.         mQueue.removeMessages(this, r, null);  
  7.     }  
  8.   
  9.     /** 
  10.      * Remove any pending posts of Runnable <var>r</var> with Object 
  11.      * <var>token</var> that are in the message queue.  If <var>token</var> is null, 
  12.      * all callbacks will be removed. 
  13.      */  
  14.     public final void removeCallbacks(Runnable r, Object token)  
  15.     {  
  16.         mQueue.removeMessages(this, r, token);  
  17.     }  
  18. </span>  


下面就是重头戏SendMessage:

 

 

[java]  view plain copy
  1. <span style="font-size:14px;"/** 
  2.      * Pushes a message onto the end of the message queue after all pending messages 
  3.      * before the current time. It will be received in {@link #handleMessage}, 
  4.      * in the thread attached to this handler. 
  5.      *   
  6.      * @return Returns true if the message was successfully placed in to the  
  7.      *         message queue.  Returns false on failure, usually because the 
  8.      *         looper processing the message queue is exiting. 
  9.      */  
  10.     public final boolean sendMessage(Message msg)  
  11.     {  
  12.         return sendMessageDelayed(msg, 0);  
  13.     }</span>  

把一个消息插入到当前所有正在等待执行的消息的后面。它会在当前线程所关联的handler的handleMessage方法中被处理。我们看到这个方法主要是调用了441行的sendMessageDelayed方法(延迟0秒发送消息):

 

 

[java]  view plain copy
  1. <span style="font-size:14px;">/** 
  2.      * Enqueue a message into the message queue after all pending messages 
  3.      * before (current time + delayMillis). You will receive it in 
  4.      * {@link #handleMessage}, in the thread attached to this handler. 
  5.      *   
  6.      * @return Returns true if the message was successfully placed in to the  
  7.      *         message queue.  Returns false on failure, usually because the 
  8.      *         looper processing the message queue is exiting.  Note that a 
  9.      *         result of true does not mean the message will be processed -- if 
  10.      *         the looper is quit before the delivery time of the message 
  11.      *         occurs then the message will be dropped. 
  12.      */  
  13.     public final boolean sendMessageDelayed(Message msg, long delayMillis)  
  14.     {  
  15.         if (delayMillis < 0) {  
  16.             delayMillis = 0;  
  17.         }  
  18.         return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);  
  19.     }</span>  

这个方法主要是在delayMillis时间后发送消息。调用的是467行的sendMessageAtTime方法:

 

 

[java]  view plain copy
  1. <span style="font-size:14px;">/** 
  2.      * Enqueue a message into the message queue after all pending messages 
  3.      * before the absolute time (in milliseconds) <var>uptimeMillis</var>. 
  4.      * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b> 
  5.      * You will receive it in {@link #handleMessage}, in the thread attached 
  6.      * to this handler. 
  7.      *  
  8.      * @param uptimeMillis The absolute time at which the message should be 
  9.      *         delivered, using the 
  10.      *         {@link android.os.SystemClock#uptimeMillis} time-base. 
  11.      *          
  12.      * @return Returns true if the message was successfully placed in to the  
  13.      *         message queue.  Returns false on failure, usually because the 
  14.      *         looper processing the message queue is exiting.  Note that a 
  15.      *         result of true does not mean the message will be processed -- if 
  16.      *         the looper is quit before the delivery time of the message 
  17.      *         occurs then the message will be dropped. 
  18.      */  
  19.     public boolean sendMessageAtTime(Message msg, long uptimeMillis)  
  20.     {  
  21.         boolean sent = false;  
  22.         MessageQueue queue = mQueue;  
  23.         if (queue != null) {  
  24.             msg.target = this;  
  25.             sent = queue.enqueueMessage(msg, uptimeMillis);  
  26.         }  
  27.         else {  
  28.             RuntimeException e = new RuntimeException(  
  29.                 this + " sendMessageAtTime() called with no mQueue");  
  30.             Log.w("Looper", e.getMessage(), e);  
  31.         }  
  32.         return sent;  
  33.     }</span>  


这个方法才是真正执行插入到队列的操作,把message插入到消息队列中。

 

像386行到427行等发送消息,均是调用sendMessageAtTime方法:

 

[java]  view plain copy
  1. <span style="font-size:14px;">    /** 
  2.      * Sends a Message containing only the what value. 
  3.      *   
  4.      * @return Returns true if the message was successfully placed in to the  
  5.      *         message queue.  Returns false on failure, usually because the 
  6.      *         looper processing the message queue is exiting. 
  7.      */  
  8.     public final boolean sendEmptyMessage(int what)  
  9.     {  
  10.         return sendEmptyMessageDelayed(what, 0);  
  11.     }  
  12.   
  13.     /** 
  14.      * Sends a Message containing only the what value, to be delivered 
  15.      * after the specified amount of time elapses. 
  16.      * @see #sendMessageDelayed(android.os.Message, long)  
  17.      *  
  18.      * @return Returns true if the message was successfully placed in to the  
  19.      *         message queue.  Returns false on failure, usually because the 
  20.      *         looper processing the message queue is exiting. 
  21.      */  
  22.     public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {  
  23.         Message msg = Message.obtain();  
  24.         msg.what = what;  
  25.         return sendMessageDelayed(msg, delayMillis);  
  26.     }  
  27.   
  28.     /** 
  29.      * Sends a Message containing only the what value, to be delivered  
  30.      * at a specific time. 
  31.      * @see #sendMessageAtTime(android.os.Message, long) 
  32.      *   
  33.      * @return Returns true if the message was successfully placed in to the  
  34.      *         message queue.  Returns false on failure, usually because the 
  35.      *         looper processing the message queue is exiting. 
  36.      */  
  37.   
  38.     public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {  
  39.         Message msg = Message.obtain();  
  40.         msg.what = what;  
  41.         return sendMessageAtTime(msg, uptimeMillis);  
  42.     }</span>  


发送空消息,使用Message.obtain()方法获得一个Message(上面已经讲道这个方法)进行发送。

 

在往下495行sendMessageAtFrotOfQueue:

 

[java]  view plain copy
  1. <span style="font-size:14px;"/** 
  2.      * Enqueue a message at the front of the message queue, to be processed on 
  3.      * the next iteration of the message loop.  You will receive it in 
  4.      * {@link #handleMessage}, in the thread attached to this handler. 
  5.      * <b>This method is only for use in very special circumstances -- it 
  6.      * can easily starve the message queue, cause ordering problems, or have 
  7.      * other unexpected side-effects.</b> 
  8.      *   
  9.      * @return Returns true if the message was successfully placed in to the  
  10.      *         message queue.  Returns false on failure, usually because the 
  11.      *         looper processing the message queue is exiting. 
  12.      */  
  13.     public final boolean sendMessageAtFrontOfQueue(Message msg)  
  14.     {  
  15.         boolean sent = false;  
  16.         MessageQueue queue = mQueue;  
  17.         if (queue != null) {  
  18.             msg.target = this;  
  19.             sent = queue.enqueueMessage(msg, 0);  
  20.         }  
  21.         else {  
  22.             RuntimeException e = new RuntimeException(  
  23.                 this + " sendMessageAtTime() called with no mQueue");  
  24.             Log.w("Looper", e.getMessage(), e);  
  25.         }  
  26.         return sent;  
  27.     }</span>  


把一个消息插入到message queue的队首。但是我们注意到在SendMessageAtTime中插入队列代码:

 

 

[java]  view plain copy
  1. <span style="font-size:14px;">queue.enqueueMessage(msg, uptimeMillis);</span>  


在uptimeMillis时间后插入到队列,而在sendMessageAtFrotOfQueue中插入队列代码:

 

 

[java]  view plain copy
  1. <span style="font-size:14px;">queue.enqueueMessage(msg, 0)</span>  


按照字面意思理解,就是立即插入队列,但是立刻插入队列也不能实现插到队首。那到底是如何实现的哪?这一点,将在MessageQueue源码分析中揭晓。

 

从511行到535行是从消息队列中删除对应的消息:

 

[java]  view plain copy
  1. <span style="font-size:14px;">    /** 
  2.      * Remove any pending posts of messages with code 'what' that are in the 
  3.      * message queue. 
  4.      */  
  5.     public final void removeMessages(int what) {  
  6.         mQueue.removeMessages(this, what, nulltrue);  
  7.     }  
  8.   
  9.     /** 
  10.      * Remove any pending posts of messages with code 'what' and whose obj is 
  11.      * 'object' that are in the message queue.  If <var>token</var> is null, 
  12.      * all messages will be removed. 
  13.      */  
  14.     public final void removeMessages(int what, Object object) {  
  15.         mQueue.removeMessages(this, what, object, true);  
  16.     }  
  17.   
  18.     /** 
  19.      * Remove any pending posts of callbacks and sent messages whose 
  20.      * <var>obj</var> is <var>token</var>.  If <var>token</var> is null, 
  21.      * all callbacks and messages will be removed. 
  22.      */  
  23.     public final void removeCallbacksAndMessages(Object token) {  
  24.         mQueue.removeCallbacksAndMessages(this, token);  
  25.     }</span>  


541行,检查消息队列中是否存在相对应的消息:

 

 

[java]  view plain copy
  1. <span style="font-size:14px;">   /** 
  2.      * Check if there are any pending posts of messages with code 'what' in 
  3.      * the message queue. 
  4.      */  
  5.     public final boolean hasMessages(int what) {  
  6.         return mQueue.removeMessages(this, what, nullfalse);  
  7.     }  
  8.   
  9.     /** 
  10.      * Check if there are any pending posts of messages with code 'what' and 
  11.      * whose obj is 'object' in the message queue. 
  12.      */  
  13.     public final boolean hasMessages(int what, Object object) {  
  14.         return mQueue.removeMessages(this, what, object, false);  
  15.     }</span>  


555行:获取当前looper:

 

 

[java]  view plain copy
  1. <span style="font-size:14px;">public final Looper getLooper() {  
  2.         return mLooper;  
  3.     }</span>  


往下,dump方法,从字面意思上理解:转储,具体作用,还不太了解,将在Looper源码解析中分析下。

 

 

[java]  view plain copy
  1. <span style="font-size:14px;"public final void dump(Printer pw, String prefix) {  
  2.         pw.println(prefix + this + " @ " + SystemClock.uptimeMillis());  
  3.         if (mLooper == null) {  
  4.             pw.println(prefix + "looper uninitialized");  
  5.         } else {  
  6.             mLooper.dump(pw, prefix + "  ");  
  7.         }  
  8.     }</span>  


575行,获取当前Messenger:

 

 

[java]  view plain copy
  1. <span style="font-size:14px;">final IMessenger getIMessenger() {  
  2.         synchronized (mQueue) {  
  3.             if (mMessenger != null) {  
  4.                 return mMessenger;  
  5.             }  
  6.             mMessenger = new MessengerImpl();  
  7.             return mMessenger;  
  8.         }  
  9.     }</span>  


关于Messenger信使类,请关注以后源码分析。

 

591行:将一个Runnable封装成一个Message。

 

[java]  view plain copy
  1. <span style="font-size:14px;"private final Message getPostMessage(Runnable r) {  
  2.         Message m = Message.obtain();  
  3.         m.callback = r;  
  4.         return m;  
  5.     }  
  6.   
  7.     private final Message getPostMessage(Runnable r, Object token) {  
  8.         Message m = Message.obtain();  
  9.         m.obj = token;  
  10.         m.callback = r;  
  11.         return m;  
  12.     }</span>  


getPostMessage这个方法在上面所说的post系列方法中,被广泛使用。

 

最后,604行,处理message里面的runnable消息,直接调用了run方法。

 

[java]  view plain copy
  1. <span style="font-size:14px;">private final void handleCallback(Message message) {  
  2.         message.callback.run();  
  3.     }</span>  

猜你喜欢

转载自2129286.iteye.com/blog/2064574
今日推荐