`

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 plaincopy
  1. final MessageQueue mQueue;  
  2.     final Looper mLooper;  
  3.     final Callback mCallback;  
  4.     IMessenger mMessenger;  

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

 

 

[java] view plaincopy
  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 plaincopy
  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 plaincopy
  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 plaincopy
  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 plaincopy
  1. /** 
  2.      * Subclasses must implement this to receive messages. 
  3.      */  
  4.     public void handleMessage(Message msg) {  
  5.     }  


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

[java] view plaincopy
  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 plaincopy
  1. private final void handleCallback(Message message) {  
  2.         message.callback.run();  
  3.     }  

 

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

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

 

[java] view plaincopy
  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 plaincopy
  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 plaincopy
  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 plaincopy
  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 plaincopy
  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 plaincopy
  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 plaincopy
  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 plaincopy
  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 plaincopy
  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 plaincopy
  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 plaincopy
  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 plaincopy
  1. <span style="font-size:14px;">queue.enqueueMessage(msg, uptimeMillis);</span>  


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

 

 

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


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

 

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

 

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


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

 

 

[java] view plaincopy
  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 plaincopy
  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 plaincopy
  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 plaincopy
  1. <span style="font-size:14px;">private final void handleCallback(Message message) {  
  2.         message.callback.run();  
  3.     }</span>  
分享到:
评论

相关推荐

    Android代码-Android 一些重要知识点解析整理

    Android AsyncTask 完全解析,带你从源码的角度彻底理解 Android 异步消息处理机制完全解析,带你从源码角度彻底理解 Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系 Android消息...

    zxing.java源码解析-StudyRoad:Java&Android开发知识点备忘

    zxing.java源码解析 StudyRoad Java & Android 知识点备忘 Java SE Thinking in Java [Java I/O](/Thinking-in-Java/Java IO.md) Android Android组件 Drawable 自定义Drawable View View工作过程 View事件分发机制 ...

    Android代码-Android_Blog_Demos

    Android_Blog_Demos 存储CSDN博客的一些源码...Android IntentService完全解析 当Service遇到Handler 详细 Android 高清加载巨图方案 拒绝压缩图片 ViewDragHelper实战 自己打造Drawerlayout Android UI性能优化实

    zxing.java源码解析-AndroidBasicStudy:对com.google.zxing3.3.3二次封装,形成jar包,可自定义

    zxing.java源码解析 AndroidBasic Study Qrcode封装 对com.google.zxing:core:3.3.3二次封装,形成jar包,可自定义view,可控制解码算法等。 IoC思想实现的简易ViewBinder 利用注解,反射实现布局的注入、控件注入、...

    Handler Message源码分析及手写实现02.mp4

    Android Handler Message源码解析和手写实现

    深入理解Android:卷I--详细书签版

     第5章讲解了Android源码中常用的类,如sp、wp、RefBase、Thread类、同步类、Java中的Handler类以及Looper类。这些类都是Android中最常用和最基本的,只有掌握这些类的知识,才 能在分析后续的代码时游刃有余。 ...

    android 使用Sax解析XML 源码实例

    下面是一个SAX解析XML的示例(有点长,因为详细注解了SAX事件处理的所有方法),SAX API中主要有四种处理事件的接口,它们分别是ContentHandler,DTDHandler, EntityResolver 和 ErrorHandler 。下面的例子可能...

    消息循环 Looper 及其源码解析

    Android 消息处理机制之四: 消息循环 Looper 及其源码解析 http://blog.csdn.net/ahuier/article/details/17103517

    疯狂Android讲义源码

     第1章 Android应用与开发环境 1  1.1 Android的发展和历史 2  1.1.1 Android的发展和简介 2  1.1.2 Android平台架构及特性 3  1.2 搭建Android开发环境 5  1.2.1 下载和安装Android SDK 5  1.2.2 安装...

    老罗android视频开发源码和ppt经典

    以下为视频源码目录: 一、Android入门介绍 视频教程 1.1 android系统介绍 1.2 android系统框架的介绍 1.3 如何搭建android开发环境 1.4 android生命周期的介绍 1.5 android使用全局变量传递数据 1.6 android使用...

    深入Android HandlerThread 使用及其源码完全解析

    关联篇:深入Android的消息机制源码详解-Handler,MessageQueue与Looper关系 关联篇:Handler内存泄漏及其解决方案 本篇我们将来给大家介绍HandlerThread这个类,以前我们在使用线程执行一个耗时任务时总会new一个...

    深入Android Handler,MessageQueue与Looper关系

    关联篇:HandlerThread 使用及其源码完全解析 关联篇:Handler内存泄漏详解及其解决方案 一说到Android的消息机制,自然就会联想到Handler,我们知道Handler是Android消息机制的上层接口,因此我们在开发过程中也只...

    Android AsyncTask使用以及源码解析

    在子线程操作完成以后我们可以通过Handler进行发送消息,通知UI进行一些更新操作(具体使用及其原理可以查看Android的消息机制——Handler的工作过程这篇文章)。当然为了简化我们的操作,在Android1.5以后为我们...

    Android天气预报Demo源码

    本Demo是一个Android端天气预报系统,利用和风天气API获取指定城市天气包含okhttp请求,handler的使用和复杂JSON的解析。

    AsyncTask 源码解析.pdf

    Handler 常用来多线程之间传递消息,AsyncTask 内部实现 InternalHandler,用来发送和处理消息 MESSAGE_POST_RESULT、MESSAGE_POST_PROGRESS,对应 AsyncTask 的回调方法 onProgressUpdate 和 onPostExecute,这两个...

    Android开发艺术探索

     3.4.2 事件分发的源码解析 / 144  3.5 View的滑动冲突 / 154  3.5.1 常见的滑动冲突场景 / 155  3.5.2 滑动冲突的处理规则 / 156  3.5.3 滑动冲突的解决方式 / 157  第4章 View的工作原理 / 174  4.1 初识...

    百度地图开发java源码-blog-backup:学习文章,也是我博客的备份

    的事件分发机制实例和源码解析。 本篇参照郭神 Blog 中的实例,来分析 ViewGroup 的事件分发机制。 本章介绍 View(视图) 动画相关概念以及应用。 本篇介绍 Handler 和 Message 以及 Looper 的基本用法和工作原理。 ...

    Android开发艺术探索.任玉刚(带详细书签).pdf

    3.4.2 事件分发的源码解析 144 3.5 View的滑动冲突 154 3.5.1 常见的滑动冲突场景 155 3.5.2 滑动冲突的处理规则 156 3.5.3 滑动冲突的解决方式 157 第4章 View的工作原理 174 4.1 初识ViewRoot和DecorView ...

    Google Android SDK开发范例大全(完整版附部分源码).pdf

    包含部分书中源码 目录 第1章 了解.深入.动手做. 1.1 红透半边天的Android 1.2 本书目的及涵盖范例范围 1.3 如何阅读本书 1.4 使用本书范例 1.5 参考网站 第2章 Android初体验 2.1 安装AndroidSDK与ADTplug...

Global site tag (gtag.js) - Google Analytics