从源码角度分析android中的消息机制

前言:

 android中的消息机制是每个android开发工程师必须要了解的,所以这篇文章就从源码的角度来解析整个android消息机制的运作流程。
先从网上盗个图,android消息机制的运行流程:
从源码角度分析android中的消息机制
由三大组件组成-Handler(从消息队列中获取消息并处理消息),MessageQueue(Message)(消息队列),Looper(在主线程也就是我们的UI线程中创建的消息循环).
我们知道每个android应用的入口都是通过ActivityThread的main()方法, android的消息机制就是在其中创建的。
消息机制传递的就是消息Message,而消息Message是放入到我们的消息队列MessageQueue这都没有啥好详细叙述的。要知道我们的消息放入到消息队列中并不够,我们还需要对消息进行操作,并且当你程序运行的时候,这个消息机制是伴随着你整个程序的声明周期的。所以不难理解为毛它需要在程序运行的入口函数中创建。而循环操作这些消息就需要Looper了。说了这么久的main()方法,我们就来看下它是如何创建我们的消息循环的。
从源码角度分析android中的消息机制
可以看到我标记的两个红框,Looper.prepareMainLooper();这个方法就是创建我们的消息循环,我们继续追踪源码。
从源码角度分析android中的消息机制

从源码角度分析android中的消息机制
可以看到,perpareMainLooper()方法中有执行了我们的myLooper()返回我们的消息循环Looper.这样我们的消息循环就创建了,其实这里还有一点就是在perpareMainLooper()方法中的执行的prepare(false),我们知道你通过handler发送的消息最终是要执行到UI线程中的,而prepare(false)中执行的操作就是把我们创建的Looper关联到我们的UI线程中,这样UI线程就能执行我们所发送的消息。这里就不深究了,有兴趣的可以研究源码了解。
好了,我们的Looper创建了,前面说了,他是用来处理我们发送到MessageQueue中的message的,同样的为了保证我们的UI线程不会主动退出,所以他会执行死循环,把消息操作放入到死循环中来处理,所以我们就来看下他的运行代码也就是Looper.loop()

从源码角度分析android中的消息机制
这里我们只需关心两个红框中的执行的方法,先看下画横线的异常,有没有感觉很熟悉,就是在子线程中没有Looper,前面就说过在prepare(false),中把Looper和我们的UI线程关联起来了。也就是说每个Looper会关联一个线程,而对应的线程会取出消息队列中的消息来执行。这样也就是整个消息机制所存在的作用了,避免在子线程中处理UI操作。
第一个红框,这看变量的命名都能理解,是从消息队列MessageQueue中获取消息;
第二个红框就是msg.target来执行dispatchMessage()方法,而这个target也就是我们的handler,看下Message的源码就能懂了。

从源码角度分析android中的消息机制

所以最终还是到Handler这来了,所以接下来分析Handler。
从源码角度分析android中的消息机制
可以看到 其中Looper为null时抛出的异常,这个大家肯定很熟悉了,就是在子线程中创建Handler所抛出的异常,这也是为什么我们的Handler发送的消息能在UI线程中执行了,Handler与Looper想关联,而我们的Looper又与我们的UI线程想关联,这样就相当于我们的Handler与UI线程向关联了。一般情况下是消息队列只有一个也就是我们的UI线程中的消息队列,当然也有特殊情况,有兴趣的可以看下HandlerThread的源码。
说了这么多,我们才解析完Handler的构造方法,接下来就继续分析上面红框中的标识的Hanlder的dispatchMessage()方法
从源码角度分析android中的消息机制
可以看到,上面分两部分,第一部分是msg.callback不为空的时候,而第二部分就是执行我们的handleMessage(msg)的回调了,这个熟悉吧,我们重点看下第一部分。
handleCallback(msg)方法执行的是什么
从源码角度分析android中的消息机制
可以看到它执行的是message.callback.run()方法,又绕到我们的Message中了,好吧,我们只好又来看下Message中的callback是啥。
看Message的源码可以知道这个callback是一个Runnable对象,其实仔细一想这是要在ui线程中执行的操作,我们除了handmessage还有个操作就是Handler.post(Runable r);所以我们直接定位到这个post方法
从源码角度分析android中的消息机制
可以看到,我们通过post方法传进来的Runnable对象又传递到getPostMessage(r)中了,那我们就继续来看这个方法

从源码角度分析android中的消息机制
可以看到,我们传进来的Runnable对象直接赋值给Message.callback变量了。所以第一部分的代码也就是执行我们Handler.post(Runnable r)中Runnable对象的run方法。这也就是为什么我们可以通过两种方式来把我们子线程中的UI操作传递到UI线程中来执行了。
以上就是Handler如何从消息队列中把消息传递到UI线程的整个流程了。
当然知道这些仅仅是不够的,我们还需要知道在源码层面上Handler是如何把消息发送到MessageQueue中的。
从源码角度分析android中的消息机制
从源码角度分析android中的消息机制
通过上面两张图的可以知道,我们无论是通过post方式还是通过sendMessage的方式发送我们的消息,都是经过
sendMessageDelayed()这个方法,所以我们只要进入到这个方法来分析就行了。
从源码角度分析android中的消息机制
可以看到sendMessageDelayed()又执行了sendMessageAtTime()方法
从源码角度分析android中的消息机制
通过sendMessageAtTime()方法就清楚明了了,通过enqueueMessage()方法来把我们的消息添加到我们的
MessageQueue中,这样整个流程就走通了。
好了,android中的消息机制就分析到这了,希望能从源码的角度来让你更加理解android中的消息机制。自己有
兴趣的同学,可以下载源码,跟着上面的流程走一遍,这样以后无论是工作还是面试android的消息机制都难不倒你了。