主要概念
Android的消息机制主要是指Handler的运行机制。
Handler的运行需要底层的MessageQueue和Looper的支撑。
MessageQueue即消息队列,采用的的单链表的数据结构来存储消息列表。MessageQueue只是一个消息存储单元。
Looper是已无线循环的方式,去查找是否有新的消息,有新消息就去处理,没有的一直等待。Looper内部还有一个特殊的概念,就是ThreadLocal,它不是线程,它的作用是在每个线程中存储数据。Handler创建的时候会采用当前线程的Looper来构造消息循环系统。Handler内部是通过ThreadLocal来获取当前线程的Looper,ThreadLocal可以在不同的线程中互不干扰的存储并提供数据。
注意:线程默认是没有Looper的,要是用Handler必须为线程创建Looper。在Android的UI线程中,即ActivityThread,它被创建的时候会初始化Looper,这就是为什么主线程能默认使用Handler的原因。
消息机制概述
Handler的主要作用是将一个任务切换到某个指定的线程中去。因为Android规定访问UI只能在主线程中进行操作。之所以不能在子线程中操作UI,这是因为Android的UI控件不是线程安全的。在多线程并发访问控件时UI控件可能处于不可预期的状态。所以系统提供Handler主要原因是为了解决在子线程无法访问UI的矛盾。
消息机制分析
ThreadLocal的工作原理
ThreadLocal是一个线程内部的数据存储类。通过它可以在指定线程中存储数据。其它线程无法访问该线程的数据。
当某些数据是以线程为作用域并且不同线程具有不同的数据副本的时候,可以考虑使用ThreadLocal。
ThreadLocal最主要的两个方法,set和get。它们操作的数据是当前线程的ThreadLocal.Values。
消息队列的工作原理
MessageQueue主要包括两个操作enqueueMessage(插入)和next(读取)。
enqueueMessage:它的主要操作其实就是单链表的插入操作。
next:是一个无限循环的方法,如果消息队列中没有消息,next方法会一直阻塞在这里。当有新消息到来时,next方法会返回这条消息,并将其从单链表中移除,
Looper的工作原理
Looper是消息机制中扮演消息循环的角色,他会不停的从MessageQueue中查看是否有新消息。又新消息就会立即处理,否则就一直阻塞在那里。
在Looper构造方法中,会创建一个MessageQueue消息队列,然后将当前线程对象保存起来。
如何为一个线程创建Looper?
在Thread的run方法中,通过Looper.prepare()可以为当前线程创建一个Looper,再通过Looper.loop()开启消息循环。
其他方法:
prepareMainLooper:这个方法是给主线程ActivityThread创建Looper使用。
getMainLooper:可以在任何地方获取到主线程的Looper
quit:直接退出Looper
quitSafely:设定一个标记,把消息队列中已存在的消息处理完成后再安全的退出。
Handler的工作原理
Handler的主要工作包含消息的发送和接受过程。消息的发送可以通过post的系列方法,和send的系列方法。post系列方法最终也是通过send的一系列方法完成。
Handler发消息的工程,只是向消息队列中插入了一条消息,MessageQueue的next方法就会返回这条消息给Looper。Looper收到这条消息就开始处理。
主线程消息循环
在Android主线程中ActivityThread的入口方法main中,通过Looper.prepareMainLooper()来创建主线程的Looper和MessageQueue,并通过Looper.loop()来开启主线程的消息循环。在消息循环开始后,ActivityThread还需要和一个Handler来和消息队列进行交互。这个Handler就是ActivityThread.H,它内部定义了一组消息类型。主要包含四大组件的启动和停止的过程。