• Android中handler,looper与messageQueue的代码解析


    在网上可随意找到关于这三者之间的关系,但总是没有在代码的角度上分析它们之间的关系。今天就在代码的角度上,理解一下这三者的关系。

    1.先看handler。

      1)handler代码中重要的三个属性:

     final MessageQueue mQueue;
     final Looper mLooper;
     final Callback mCallback;

         在handler 的默认构造函数中,有这样的代码:

     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;

         可以看出handler对应于一个looper,而这个looper是在当前主线程中唯一的looper,另外,messageQueue也是从looper中的messageQueue获取。

     /**
         * Callback interface you can use when instantiating a Handler to avoid
         * having to implement your own subclass of Handler.
         */
        public interface Callback {
            public boolean handleMessage(Message msg);
        }

          属性中的mCallback就是此回调接口的一个实例,可以避免另外实现Handler来处理message。

      此外,handler的四个构造函数,都是在为这几个属性赋值进行实例化,就不在此列出了。

      另外,还有一个重要的方法就是dispatchMessage,handler中的message接收处理就是通过此方法来调用处理:

       /**
         * 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);
            }
        }

    2. 接下来是looper,官方有很好的解释,就不在翻译了(翻译的不好)。

    Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.
    
    Most interaction with a message loop is through the Handler class.
    
    This is a typical example of the implementation of a Looper thread, using the separation of prepare() and loop() to create an initial Handler to communicate with the Looper.
    
      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();
          }
      }

      可以看出一个线程拥有一个message looper。在looper类中,其拥有两个属性

     final MessageQueue mQueue;
     final Thread mThread;

      通过prepare方法保证其只有一个looper。

     public static void prepare() {
            if (sThreadLocal.get() != null) {
                throw new RuntimeException("Only one Looper may be created per thread");
            }
            sThreadLocal.set(new Looper());
        }

     在looper内的loop方法中,通过获取looper内的messageQueue,用while(true)来循环遍历当前的messageQueue,并通过message的target的dispatchMessage方法来触发handler的sendMessage方法。

    public static void loop() {
            Looper me = myLooper();
            if (me == null) {
                throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
            }
            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();
            
            while (true) {
                Message msg = queue.next(); // might block
                if (msg != null) {
                    if (msg.target == null) {
                        // No target is a magic identifier for the quit message.
                        return;
                    }
    
                    long wallStart = 0;
                    long threadStart = 0;
    
                    // 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);
                        wallStart = SystemClock.currentTimeMicro();
                        threadStart = SystemClock.currentThreadTimeMicro();
                    }
    
                    msg.target.dispatchMessage(msg);
    
                    if (logging != null) {
                        long wallTime = SystemClock.currentTimeMicro() - wallStart;
                        long threadTime = SystemClock.currentThreadTimeMicro() - threadStart;
    
                        logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
                        if (logging instanceof Profiler) {
                            ((Profiler) logging).profile(msg, wallStart, wallTime,
                                    threadStart, threadTime);
                        }
                    }
    
                    // 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();
                }
            }
        }

      再来看looper的私有构造函数:

    private Looper() {
            mQueue = new MessageQueue();
            mRun = true;
            mThread = Thread.currentThread();
        }

    可以看到looper是跟当前主线程绑定的。

    3. 要了解MessageQueue,先看下Message实体。在Message中重要的字段属性,大家常常都用到,其中我感觉重要的有两个:一个是Handler target;另一个是Message next;有了next,我们便可以知道MessageQueue是如何添加message以及删除Message了以及message的遍历。

    好了,先介绍到这里了,内容有点略简单,更多内容感觉还得研读代码,能够调试源码程序更好了。

    PS:第一次写博客,有不足的地方,大家家多多指正,非常感谢。

    ——————————如果不豁出性命的话,也是无法开创未来的。
  • 相关阅读:
    数据库准入规则
    ubuntu go 开发环境搭建
    PHP 异步执行方式
    python 连接 hive数据库环境搭建
    Swift 发送邮件和附件
    python 爬取动态数据
    git 新建项目的一些操作
    php 爬取数据
    通过NGINX location实现一个域名访问多个项目
    Linux系统Web网站目录和文件安全权限设置
  • 原文地址:https://www.cnblogs.com/thirller/p/3419277.html
Copyright © 2020-2023  润新知