Android的Handler、MessageQueue、Runnable和Looper的联系(源码选自21版本)

Android的Handler、MessageQueue、Runnable和Looper的联系(源码选自21版本)

 

写过一段时间Android代码的程序猿朋友们可能都知道:Looper是一个循环,维护一个消息队列MessageQueue,Handler是一些事件,循环的放入队里中事件然后去处理和回调,但也许还没来得及看一看源码,这块是咋工作的,我这里小做整理,以防以后忘记了,回过来再回味一下【高手欢迎批评指正~】。

在这里,通过下面的分析,我想要回答三个问题:

1.他们四个是怎么联系在一起的?

2.我们在用Handler的时候,一直在脑海中的原理如何从源码级别体会到的呢?

3.应用在运行的时候,它是咋开启的呢?

通过Looper源码的分析,可以找到Handler、MessageQueue和Looper的联系。Looper.java的doc文档也大概介绍了Handler的工作机制,咋一读可能品味不到什么,但捋一遍源码再回头看,其实说的很明白,即:

class LooperThread extends Thread {
        public Handler mHandler;
        public void run() {
            Looper.prepare();
            mHandler = new Handler() {
                public void handleMessage(Message msg) {
                
                }
            };
            Looper.loop();
       }
    }


从头说起,当我们new一个Handler的时候,即Handler mHandler = new Handler();跟踪Handler.java类,可以看到,它访问了Handler(null, false)方法。这里面传入了Looper,即mLooper = Looper.myLooper()【mLooper肯定不会为null了,否则Handler肯定会创建失败的,这个后面提】;将Looper的MessageQueue传递到了Handler。那么,可以看到了,Looper内一定维护了一个队列了。

我们可能会调用mHandler的post(Runnable)方法,这样就可以执行一段我们想要的操作(当然,也可以使用sendMessage的方式,这个到底有什么区别?)。跟踪post这个方法可以看到,它是将Runnable装换成了Message,同时将runnable传递给Message的callaback参数。它访问了enqueueMessage(),这个Message入队了。

消息入队了,那么它是怎么执行的呢?这个问题由Looper.java来回答。回到Handler的构造函数,它调用了myLooper(),查看这个方法,它是从ThreadLocal里面取了一个Looper。为什么ThreadLocal.get()肯定不会为空呢?首先,可以看看最上面那段LooperThread 的代码,它说:在我们new Handler之前,肯定是系统已经调用了prepare()方法装填了一个Looper了。那究竟这段代码是怎么调用的呢?这个问题就要到ActivityThread.java(附录I、II)这个类里面可以看到。原来,在应用进程的主线程在创建的时候,它就调用了prepare()方法了嘛,代码如下(问题三在这里):

        Looper.prepareMainLooper();        ...        Looper.loop();

所以,在我们new Hanlder之前,肯定ThreadLocal内已经非空了。看到了,这里调用了loop()方法。查看这个方法,我们可以找到一些信息:

    1)取出消息队列中的消息:

Message msg = queue.next(); 

    2)执行我们想要的操作:

        msg.target.dispatchMessage(msg);

这里,target就是我们的Handler(这个怎么弄的,可以看obtainMessage())。串联起来了吧, 一般我们就是通过dispatchMessage()来执行我们想要的操作的,对吧。

  3)这里有个一直在的循环,循环着处理着消息队列中的操作。

  应该还有一个问题,我最开始是使用post来执行一段操作的,虽然说过了将它转换成了Message,但并没有重写dispatchMessage,那么传入到MessageRunnable是咋工作的呢,看一下handlerdispatchMessage,一目了然,使用post的调用方式callback 非空,通过handleCallback访问了message.callback.run();而通过sendMessage的方式callback 可能为空,自然就会走handleMessage()了【代码中还有一点细节,mCallback 也非空的情况,不提了】。

public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
}

最后再总结一下,Looper内维护一个循环,当应用ActivityThread第一次访问的时候,开启这个循环,随后,通过Handler将Message(sendMessage或者post传入的由Runnable构建的Message)放入Looper内的MessageQueue。

我感觉差不多说清楚了,暂时我是对Android的消息机制这段比以前认识更多了,还有啥我没说清楚的,可以继续一起研究。不得不提一下,强烈推荐一本书《深入理解Android内核设计思想》,其实可以看到,我的很多认识也是从这本书学到的,不能忘记挖井人!

 

附录:

[1] ActivityThread简介:http://blog.csdn.net/myarrow/article/details/14223493

[2] Acitvity源码:http://code.taobao.org/svn/cnAndroidSDK/trunk/dev/java/android/app/ActivityThread.java

[3] ThreadLocalhttp://blog.csdn.net/aa747604141/article/details/17610269

        [4] 《深入理解Android内核设计思想》.林学森

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值