`

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程序源码--测试

    9. **异步编程**:Android提供了AsyncTask、Handler、Thread、Runnable等异步处理机制,源码分析可以学习如何避免主线程阻塞,提高应用响应性。 10. **权限管理**:Android的权限模型是安全管理的重要组成部分,...

    Android程序源码--贪吃蛇

    以下是对这个“Android程序源码--贪吃蛇”项目的详细解析: 1. **Android环境搭建**:首先,你需要安装Android Studio,这是Google官方提供的集成开发环境(IDE),用于编写、调试和运行Android应用。它包含了一个...

    Android应用源码---手持扫码枪APP开发源码.rar

    【Android应用源码---手持扫码枪APP开发源码】 在Android平台上开发一款手持扫码枪应用程序,需要理解并掌握一系列关键的技术点。以下是对这个压缩包文件中可能包含的知识点的详细解析: 1. **Android Studio集成...

    Android例子源码--炫酷的仪表盘网速测试源码

    以上是对"Android例子源码--炫酷的仪表盘网速测试源码"的关键知识点的详细解析,通过学习和研究这个项目,开发者不仅可以掌握Android自定义View的实现,还能深入了解网络监测、动画应用、UI设计等多个方面,对于提升...

    android应用源码-高度仿网易新闻app源码 .zip

    《Android应用开发:深度解析高度仿网易新闻App源码》 在移动互联网时代,Android作为全球最广泛使用的智能手机操作系统之一,其应用开发的重要性不言而喻。本篇将深入探讨一款高度仿网易新闻App的源码,通过分析其...

    Android应用源码----基于LBS的社交软件包括服务端 .zip

    【Android应用源码——基于LBS的社交软件包括服务端】是一个典型的移动开发项目,它展示了如何构建一个基于位置服务(LBS,Location-Based Services)的社交应用。在这个项目中,我们有两个主要部分:`monolog-web-...

    android-screen-monitor源码

    《深入解析Android-screen-monitor源码》 Android-screen-monitor是一款用于实时监控Android设备屏幕状态的工具,它的源码为我们提供了一个深入了解Android系统级别的屏幕监控机制的机会。这篇文章将详细探讨该源码...

    安卓Android源码——ipcamera-for-android 手机变成IP Camera.zip

    "安卓Android源码——ipcamera-for-android 手机变成IP Camera" 这个标题揭示了我们正在探讨一个特殊的Android项目,它的主要功能是将Android智能手机转化为网络摄像头,即IP Camera。IP Camera是指能够通过网络进行...

    安卓Android源码——安卓Android经典开发---豆瓣网移动客户端+讲解+源代码.rar

    《安卓Android源码解析——深度探索豆瓣移动客户端》 安卓Android平台因其开源、灵活的特性,成为了移动应用开发的重要选择。对于开发者来说,深入理解源码是提升技能、优化应用性能的关键步骤。本资料包围绕“安卓...

    Android高级应用源码-Android经典开发---豆瓣网移动客户端+讲解+源代码.zip

    《Android高级应用源码-Android经典开发---豆瓣网移动客户端+讲解+源代码》这个压缩包文件是一个关于Android开发的高级教程,包含了豆瓣网移动客户端的完整源代码和详细的讲解,旨在帮助开发者深入理解Android应用的...

    Android应用源码qiyi-IT计算机-毕业设计.zip

    《Android应用源码解析——基于"qiyi-IT计算机-毕业设计.zip"的深度学习》 在当今的移动互联网时代,Android应用开发已经成为IT行业不可或缺的一部分,尤其对于计算机科学和技术专业的毕业生而言,掌握Android应用...

    Android应用源码之-Image-Cache-master.rar

    《深入解析Android应用源码:Image-Cache机制》 在Android开发中,高效的图片加载与缓存机制是提升用户体验的关键因素之一。"Android应用源码之-Image-Cache-master.rar"是一个专注于图片缓存实现的开源项目,它为...

    Android源码解析

    ### Android源码解析知识点概述 #### 公共技术点概览 - **Java反射** - Java反射机制允许运行时检查类、接口、字段和方法的信息,并能够动态地调用方法和修改字段值。 - **应用场景**:动态加载类、实现插件化...

    Android_Learning-master.zip

    《深入探索Android学习之路——基于Android_Learning-master项目解析》 Android_Learning-master.zip这个压缩包,正如其名,是一个包含Android学习资源的项目库,是开发者深入理解Android开发技术的重要资料。它...

    Android应用源码 -二维码识别源码.zip

    这个“Android应用源码 -二维码识别源码.zip”文件包含了一个完整的Android应用,专门用于识别和解析二维码。这个源码可以帮助开发者深入理解如何在Android应用中集成二维码扫描功能。 首先,我们要了解二维码...

    ANDROID源码-sailorcast - 水手放映室

    "ANDROID源码-sailorcast - 水手放映室"是一个开源项目,主要关注的是Android平台上的应用开发。从项目名称来看,"水手放映室"可能是一个媒体播放或内容展示的应用,而"Sailorcast"可能是这个应用的核心模块或者框架...

    android应用源码闹钟-秒表-倒计时-时钟四合一源码.zip

    该压缩包文件“android应用源码闹钟-秒表-倒计时-时钟四合一源码.zip”包含了Android平台上一款集成了四种功能的应用的源代码:闹钟、秒表、倒计时和时钟。这是一份非常适合Android开发者学习和参考的资源,可以帮助...

    android源码-HiBabyDragon

    《Android源码解析:构建HiBabyDragon应用》 在当今移动开发领域,Android操作系统占据了重要的地位,而深入理解Android源码对于开发者来说是一项至关重要的技能。本篇文章将围绕"HiBabyDragon"这一软件项目,从...

    android应用源码Zirco-browser浏览器.zip

    7. **多线程**:为了实现流畅的用户体验,浏览器可能使用多线程技术,如AsyncTask或Handler-Looper机制来处理耗时操作。 8. **缓存机制**:为了提高加载速度,浏览器通常会缓存网页数据,源码中会涉及缓存策略和...

Global site tag (gtag.js) - Google Analytics