• 【内核研究】处理者_Handler


    虽然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()函数。



  • 相关阅读:
    解决js newDate()苹果手机日期格式显示NaN
    AD 用户个人信息补充
    CSV 文件批量导入 数据库 Pandas
    【笔记】单调栈?
    【其他】Modern C++ in OI
    【笔记】网络流
    【笔记】默认构造函数和零初始化
    【笔记】正确的当前弧优化
    golang读取文件的方法
    protobuf使用
  • 原文地址:https://www.cnblogs.com/cynchanpin/p/7207910.html
Copyright © 2020-2023  润新知