码迷,mamicode.com
首页 > 其他好文 > 详细

【内核研究】处理者_Handler

时间:2014-10-09 16:59:58      阅读:243      评论:0      收藏:0      [点我收藏+]

标签:blog   http   io   使用   ar   java   for   sp   2014   

尽管MessageQueue提供了直接读/写的函数接口,但对于程序员来说,一般不直接读/写消息队列。之前了解到,在Looper.loop()函数中,当取出消息后,会回调msg.target对象的handleMessage()函数,而msg.target的类型正是Handler。

    /**
     *  Run the message queue in this thread. Be sure to call
     * {@link #quit()} to end the loop.
     */
    public static final void loop() {
        Looper me = myLooper();
        MessageQueue queue = me.mQueue;
        while (true) {
            Message msg = queue.next(); // might block
            //if (!me.mRun) {
            //    break;
            //}
            if (msg != null) {
                if (msg.target == null) {
                    // No target is a magic identifier for the quit message.
                    return;
                }
                if (me.mLogging!= null) me.mLogging.println(
                        ">>>>> Dispatching to " + msg.target + " "
                        + msg.callback + ": " + msg.what
                        );
                msg.target.dispatchMessage(msg);
                if (me.mLogging!= null) me.mLogging.println(
                        "<<<<< Finished to    " + msg.target + " "
                        + msg.callback);
                msg.recycle();
            }
        }
    }
一般使用Handler类向消息队列中发送消息,并重载Handler类的handleMessage()函数添加消息处理代码。

Handler对象只能添加到有消息队列的线程中,否则会发生异常。以下代码是Handler类的构造函数:

    /**
     * Default constructor associates this handler with the queue for the
     * current thread.
     *
     * If there isn‘t one, this handler won‘t be able to receive messages.
     */
    public Handler() {
        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }

        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can‘t create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = null;
    }
注意这句代码:

        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can‘t create handler inside thread that has not called Looper.prepare()");
        }
由以上代码可以得出结论,在构造Handler对象前,必须已经执行过Looper.prepare(),但prepare()不能被执行两次。下面是Looper.prepare()的代码:

     /** Initialize the current thread as a looper.
      * This gives you a chance to create handlers that then reference
      * this looper, before actually starting the loop. Be sure to call
      * {@link #loop()} after calling this method, and end it by calling
      * {@link #quit()}.
      */
    public static final void prepare() {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper());
    }
创建Handler对象可以在执行Looper.loop()函数之前,也可以在执行之后。

在以往的应用程序开发中,一般在Activity的初始化代码中添加Handler对象,事实上,在Activity对象被构造前,Activity所在的线程已经执行了Looper.prepare()函数。具体可查看下面的链接。

http://blog.csdn.net/manoel/article/details/39499747

一个线程中可以包含多个Handler对象。在Looper.loop()函数中,不同的Message对应不同的Handler对象,从而回调不同的handleMessage()函数。



【内核研究】处理者_Handler

标签:blog   http   io   使用   ar   java   for   sp   2014   

原文地址:http://blog.csdn.net/manoel/article/details/39930641

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!