Android深入分析MessageQueue和Looper(FrameWork JAVA部分)

    Looper是Android用来进行线程间通信的,一般是UI线程和工作线程通信,对于很多人最难理解的是JAVA层Handler, Looper, MessageQueue与线程的关系,一旦关系理解了你就明白其中的工作原理了

    最重要的准备知识点是ThreadLocal,如果这个不能理解就没法看下文了参考链接http://blog.csdn.net/zdp072/article/details/39155143

   
   一: 形象的描述一下 Looper MessageQueue 与线程的关系:线程好比一艘船,Looper依赖于线程,每个船舱里都有1个Looper,然后这个Looper有1个MessageQueue,Looper会不停的循环看这个MessageQueue有没有消息,如果有消息就会抛给船甲板上的员工(Handler),员工也会把消息丢到它所在船上的MessageQueue里面

  包含的知识点如下
  1: 也就是1个线程只有1个Looper和MessageQueue,但是这个线程可以有多个Handler
  2:Handler sendMessage是往自己所在的线程里面的MessageQueue里面发送消息
  3:Looper循环处理的MessageQueue是自己所在线程的   

可以看下图参考一下:




到这抛出了一个概念,下面我们可以分析源码来更全面的认识一下:

涉及到的源码目录

\frameworks\base\core\java\android\os\Looper.java
\frameworks\base\core\java\android\os\MessageQueue.java
\frameworks\base\core\java\android\os\Handler.java
\frameworks\base\core\java\android\os\Message.java

从这个Demo分析:
* <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.java(就是不停的从MessageQueue里面拿消息抛给船板上的Handler)
分析Looper.prepare()做了什么东西




这个sThreadLocal.set(new Looper)是啥意思呢?所以要理解ThreadLocal是干啥的,其实就是ThreadLocal有块Map内存,Key是线程,Value在这是Looper,每次调用sThreadLocal.set()的时候就是更新这个Map集合,Key是线程自己,Value是Looper对象,所以这边保证了1个线程内部只有1个对应的Looper对象


二:看一下Looper的构造函数做了什么



就是创建了一个MessageQueue然后更新变量指向调用改函数所在的线程

三:现在分析Looper.loop()是干啥的了


也就是不停的从线程里面的messgaequeue取消息,然后调用handler的dispatchmsg()

到这Looper就分析结束了内容少关键就是理解ThreadLocal



一:现在开始分析MessageQueue
MessageQueue与Native层MessageQueue其实是两套机制,讲这个前就需要做好Framewok Java层与Native层的MessagqQueue的区别
读者首先得知道我们的Looper 会首先处理Native层的消息然后再处理Java层的消息,那么Native层的消息是怎么处理的呢?这个就看下篇Native 的机制,先看下面这张图有个框架知识




这张图意思是指Java的MessagQueue会通过JNI创建一个Native的MessageQUeue,这个C++版的MessageQueue会创建一个Looper.cpp(C++版的Looper与Java版的Looper没有任何关系两码事),这个Native的Looper是通过Epoll机制去处理Native层的消息,其实Looper.cpp就是Android版的Epoll

继续分析Java层的MessageQueue看一下构造函数



通过JNI创建了Native层的MessageQueue

  /**MessageQueue取消息函数*/
    Message next() {
        // Return here if the message loop has already quit and been disposed.
        // This can happen if the application tries to restart a looper after quit
        // which is not supported.
        final long ptr = mPtr;
        if (ptr == 0) {
            return null;
        }

        int pendingIdleHandlerCount = -1; // -1 only during first iteration
        int nextPollTimeoutMillis = 0;
        for (;;) {
            if (nextPollTimeoutMillis != 0) {
                Binder.flushPendingCommands();
            }
            /**MessageQueue首先处理Native层的消息然后Java层*/
            nativePollOnce(ptr, nextPollTimeoutMillis);

            synchronized (this) {
                // Try to retrieve the next message.  Return if found.
                final long now = SystemClock.uptimeMillis();
                Message prevMsg = null;
                Message msg = mMessages;
                if (msg != null && msg.target == null) {
                    // Stalled by a barrier.  Find the next asynchronous message in the queue.
                    do {
                        prevMsg = msg;
                        msg = msg.next;
                    } while (msg != null && !msg.isAsynchronous());
                }
                if (msg != null) {
                    if (now < msg.when) {
                        // Next message is not ready.  Set a timeout to wake up when it is ready.
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        // Got a message.
                        mBlocked = false;
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
                            mMessages = msg.next;
                        }
                        msg.next = null;
                        if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                        msg.markInUse();
                        return msg;
                    }
这边就是MessageQueue的next()函数返回队列里面的消息


一:下面分析Handler内容




这样你就能明白你每次调用new Handler()的时候它会找到这个线程的looper和messageQueue

然后看handler每次怎么丢消息的




OK  到此Java层结束了

  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值