美文网首页
Android 消息机制

Android 消息机制

作者: null0007 | 来源:发表于2017-01-16 17:36 被阅读0次

    Android 消息机制

    android消息机制主要是Handler运行机制,其底层主要是MessageQueue和Looper,MessageQueue是采用单链表存储的消息列表。Looper是处理消息的无限循环。

    概述

    Handler的主要作用是将一个任务切换到某一个指定的线程中去执行。主要应用场景是在子线程里执行UI线程的操作。

    机制分析

    ThreadLocal

    ThreadLocal是线程局部变量,为每一个使用该变量的线程提供一个变量值的副本。
    这样每个线程可以改变自己的变量副本,而不会引起与其他线程的冲突。
    使用的场景是那些数据的作用域是线程并且不同线程具有不同的副本。Looper符合这样的场景。

    ThreadLoacal操作的对象是当前线程的localValues对象的table数组,通过set和get方法来访问。

    MessageQueue

    MessageQueue主要有两个操作,插入和读取,用单链表实现,因为链表具有插入和删除的优势。
    这里主要有两个方法:一个enqueue,就是链表的创建和插入过程
    一个是next就是读取消息,这里有一个无限循环,以不断的从链表里读取消息。

    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();
          }
      }
    

    Looper是消息循环,它不断的从MessageQueue里查看是否有新的消息,如果有消息,则立即处理,如果没有,则阻塞等待消息。
    prepare方法为当前线程创建Looper

     /** 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 void prepare() {
        prepare(true);
    }
    
    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }
    

    loop方法调用后就启动消息循环工作。取消息,从消息队列里娜,调用queue.next, 得到的消息为msg,然后分发消息给Handler对象(msg.target)去处理,即msg.target.dispatchMessage(msg)

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

    Handler

    Handler负责消息的发送和接收过程。发送消息用post,send,向消息队列里插入一个消息,Looper取到消息后给Handler的dispatchMessage处理消息,

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

    在ActivityThread里,定义了内部类Handler H,在main里进行Looper的创建和开启工作,然后就可以结合handler一起进行工作了。

    参考:android开发艺术探索

    相关文章

      网友评论

          本文标题:Android 消息机制

          本文链接:https://www.haomeiwen.com/subject/rcepbttx.html