Handler 源码解析

来源:互联网 发布:淘宝专业刷信誉网站 编辑:程序博客网 时间:2024/05/20 18:43
 Handler handler = new Handler() {        public void handleMessage(android.os.Message msg) {        };    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);              Message message = handler.obtainMessage();        message.obj = "1";        handler.sendMessage(message);}



一、首先看Handler的初始化:

 /**     * Default constructor associates this handler with the {@link Looper} for the     * current thread.     *     * If this thread does not have a looper, this handler won't be able to receive messages     * so an exception is thrown.     */    public Handler() {        this(null, false);    }


   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();
 //Return the Looper object associated with the current thread.  
// Returns null if the calling thread is not associated with a Looper.
        if (mLooper == null) {            throw new RuntimeException(                "Can't create handler inside thread that has not called Looper.prepare()");        }        mQueue = mLooper.mQueue;        mCallback = callback;        mAsynchronous = async;    }


在上面的流程,已经为Handler准备好了Looper和MessageQueue。



默认的这个Handler 的构造器将Handler和Looper联系在一起(这样翻译有些奇怪),也是说一个Handler必须对应一个Looper。如果没有对应的Looper,则会抛出异常。其实还有Message、Message Queue,看了很多解释,我对这些概念的理解是:

Handler相当于搬运工,

搬运的货物是Message,

搬运目的地是Message Queue(消息队列)和主线程,

Looper是仓库管理员,支配Message Queue的出仓。


关于Looper、MessageQueue等对象的初始化,我们可以在下面找到。

Android应用程序进程在启动的时候,会在进程中加载ActivityThread类,并且执行这个类的main函数,应用程序的消息循环过程就是在这个main函数里面实现的,它定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:

public final class ActivityThread {      ......        public static final void main(String[] args) {          ......            Looper.prepareMainLooper();            ......            ActivityThread thread = new ActivityThread();          thread.attach(false);                    ......            Looper.loop();            ......            thread.detach();            ......      }  }  



Handler初始化后,留了一个回调接口handleMessage(Message mes){};



二、Message


 Message message = handler.obtainMessage();

/**     * Returns a new {@link android.os.Message Message} from the global message pool. More efficient than     * creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this).     *  If you don't want that facility, just call Message.obtain() instead.     */    public final Message obtainMessage()    {        return Message.obtain(this);    }


如果不使用Message message = handler.obtainMessage()而重新new一个对象,需要将Message.target指向搬运工handler。

/**     * Same as {@link #obtain()}, but sets the value for the <em>target</em> member on the Message returned.     * @param h  Handler to assign to the returned Message object's <em>target</em> member.     * @return A Message object from the global pool.     */    public static Message obtain(Handler h) {        Message m = obtain();        m.target = h;        return m;    }



三、  handler.sendMessage(message);

/**     * Pushes a message onto the end of the message queue after all pending messages     * before the current time. It will be received in {@link #handleMessage},     * in the thread attached to this handler.     *       * @return Returns true if the message was successfully placed in to the      *         message queue.  Returns false on failure, usually because the     *         looper processing the message queue is exiting.     */    public final boolean sendMessage(Message msg)    {        return sendMessageDelayed(msg, 0);    }


/**     * Enqueue a message into the message queue after all pending messages     * before (current time + delayMillis). You will receive it in     * {@link #handleMessage}, in the thread attached to this handler.     *       * @return Returns true if the message was successfully placed in to the      *         message queue.  Returns false on failure, usually because the     *         looper processing the message queue is exiting.  Note that a     *         result of true does not mean the message will be processed -- if     *         the looper is quit before the delivery time of the message     *         occurs then the message will be dropped.     */    public final boolean sendMessageDelayed(Message msg, long delayMillis)    {        if (delayMillis < 0) {            delayMillis = 0;        }        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);    }



/**     * Enqueue a message into the message queue after all pending messages     * before the absolute time (in milliseconds) <var>uptimeMillis</var>.     * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>     * You will receive it in {@link #handleMessage}, in the thread attached     * to this handler.     *      * @param uptimeMillis The absolute time at which the message should be     *         delivered, using the     *         {@link android.os.SystemClock#uptimeMillis} time-base.     *              * @return Returns true if the message was successfully placed in to the      *         message queue.  Returns false on failure, usually because the     *         looper processing the message queue is exiting.  Note that a     *         result of true does not mean the message will be processed -- if     *         the looper is quit before the delivery time of the message     *         occurs then the message will be dropped.     */    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {        MessageQueue queue = mQueue;        if (queue == null) {            RuntimeException e = new RuntimeException(                    this + " sendMessageAtTime() called with no mQueue");            Log.w("Looper", e.getMessage(), e);            return false;        }        return enqueueMessage(queue, msg, uptimeMillis);    }


//根据方法的名称,下面对Message进行入队排序。

 private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {        msg.target = this;        if (mAsynchronous) {            msg.setAsynchronous(true);        }        return queue.enqueueMessage(msg, uptimeMillis);    }



 boolean enqueueMessage(Message msg, long when) {        if (msg.isInUse()) {            throw new AndroidRuntimeException(msg + " This message is already in use.");        }        if (msg.target == null) {            throw new AndroidRuntimeException("Message must have a target.");        }        synchronized (this) {            if (mQuitting) {                RuntimeException e = new RuntimeException(                        msg.target + " sending message to a Handler on a dead thread");                Log.w("MessageQueue", e.getMessage(), e);                return false;            }            msg.when = when;            Message p = mMessages;            boolean needWake;            if (p == null || when == 0 || when < p.when) {                // New head, wake up the event queue if blocked.                msg.next = p;                mMessages = msg;                needWake = mBlocked;            } else {                // Inserted within the middle of the queue.  Usually we don't have to wake                // up the event queue unless there is a barrier at the head of the queue                // and the message is the earliest asynchronous message in the queue.                needWake = mBlocked && p.target == null && msg.isAsynchronous();                Message prev;                for (;;) {                    prev = p;                    p = p.next;                    if (p == null || when < p.when) {                        break;                    }                    if (needWake && p.isAsynchronous()) {                        needWake = false;                    }                }                msg.next = p; // invariant: p == prev.next                prev.next = msg;            }            // We can assume mPtr != 0 because mQuitting is false.            if (needWake) {                nativeWake(mPtr);            }        }        return true;    }


上面就是已经添加消息到队列头部的操作。 现在入队操作我们就已经看明白了,那出队操作是在哪里进行的呢。(但目前我还没有找到直接调用源码中Looper.looper())


在Looper类的有这么一段说明代码:
<pre>
  *  class LooperThread extends Thread {
  *      public Handler mHandler;
  *
  *      public void run() {
  *          Looper.prepare();
  *
  *          mHandler = new Handler() {
  *              public void handleMessage(Message msg) {
  *                  // process incoming messages here
  *              }
  *          };
  *
  *          Looper.loop();
  *      }
  *  }</pre>



出队列应该有仓库管理员Looper来执行。


  /**     * Run the message queue in this thread. Be sure to call     * {@link #quit()} to end the loop.     */    public static void loop() {        final Looper me = myLooper();        if (me == null) {            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");        }        final MessageQueue queue = me.mQueue;        // Make sure the identity of this thread is that of the local process,        // and keep track of what that identity token actually is.        Binder.clearCallingIdentity();        final long ident = Binder.clearCallingIdentity();        for (;;) {            Message msg = queue.next(); // might block            if (msg == null) {                // No message indicates that the message queue is quitting.                return;            }            // This must be in a local variable, in case a UI event sets the logger            Printer logging = me.mLogging;            if (logging != null) {                logging.println(">>>>> Dispatching to " + msg.target + " " +                        msg.callback + ": " + msg.what);            }            msg.target.dispatchMessage(msg);            if (logging != null) {                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);            }            // Make sure that during the course of dispatching the            // identity of the thread wasn't corrupted.            final long newIdent = Binder.clearCallingIdentity();            if (ident != newIdent) {                Log.wtf(TAG, "Thread identity changed from 0x"                        + Long.toHexString(ident) + " to 0x"                        + Long.toHexString(newIdent) + " while dispatching to "                        + msg.target.getClass().getName() + " "                        + msg.callback + " what=" + msg.what);            }            msg.recycle();        }    }

 msg.target.dispatchMessage(msg); Message中提到msg.target就是handler.

 /**     * Handle system messages here.     */    public void dispatchMessage(Message msg) {        if (msg.callback != null) {            handleCallback(msg);        } else {            if (mCallback != null) {                if (mCallback.handleMessage(msg)) {                    return;                }            }            handleMessage(msg);        }    }





0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 每天加班很累反而失眠严重怎么办 减肥药吃了口臭嘴巴苦怎么办 上火引起的牙疼怎么办吃什么药 舌苔厚口气重怎么办应该吃什么药 宝宝老是额头热四肢不热怎么办 考老师考砸了心理崩溃了怎么办 苹果手机一会白屏一会黑屏怎么办 360云盘的东西删不了怎么办 手机邮箱打开的文件疑似病毒怎么办 电脑qq发送的文件失效了怎么办 小米4c温控文件打开是乱码怎么办 超星尔雅用学号登录密码忘了怎么办 全脸做激光去黄褐斑后脸发红怎么办 上传到微云中的视频下载不了怎么办 微云保存的小电影下载不了怎么办 苹果手机下载有云朵下载不了怎么办 手机下载登录忘了密码了怎么办 软软件被手机加密忘了密码怎么办 苹果手机想下载东西忘了密码怎么办 已经不念书几年了突然想上学怎么办 江湖风云录把王老爷子杀了怎么办 练扫踢胫骨旁边的肌肉受伤了怎么办 四个月宝宝没抱住摔了头部怎么办 老公老是跟年轻的小姑娘聊天怎么办 老婆出轨老公想离婚又舍不得怎么办 孕妇打完无痛分娩针就想睡觉怎么办 熟食店开空调菜品吹的很干怎么办 不锈钢锅在液化气烧了发黄怎么办 在小镇门面卤菜店不好卖怎么办? 被辣椒辣到嘴唇了该怎么办 沁园净水机不制水指示灯不亮怎么办 太辣了辣得胃疼怎么办 出现连接问题或mmi码无效怎么办 存折丢了怎么办卡号也不记得了 车内皮子被烂苹果腐蚀有印怎么办 锅被腐蚀后变黑色应该怎么办 后厨炉灶里的炉芯进水了怎么办 小儿九个月老是流黄鼻子该怎么办 肉炖的老了不烂怎么办 吃了凉东西现在一直打嗝应该怎么办 喝了很多水还是觉得口渴怎么办