一、简介
进程(Process)是程序的一个运行的实例,以区别“程序”这一静态的概念。线程(Thread)是CPU调用的基本单位。
二、进程的组成部分
在Android中的四大组件是进程组成的一部分,Android App在启动时,创建App进程,以及主线程(UI线程)和两个Binder线程。创建一个新工程,在工程中创建一个Activity、Service、BroadcastReceiver,分别在onCreate(...)和onReceiver(...)方法Debug 断点调试。查看Activity、Service、BroadcastReceiver组件创建及启动过程。
启动应用创建App进程:
Activity启动:
Service启动:
BroadcastReceiver启动:
由调试可以看到Activity、Service、BroadcastReceiver组件都是在主线程中创建的,其创建过程基本上一致。所以,Service、BroadcastReceiver执行耗时操作时,要在子线程中执行。
三、Runnable、Message、MessageQueue、Looper、Handler
在Android开发中,使用消息队列(message)完成线程间通信。而使用消息队列的线程就是消息循环(message looper)。消息循环不断的检查消息队列,是否有新消息。消息循环是由一个线程和一个looper组成;looper对象管理着线程的消息队列。
Android的主线程也是一个消息循环,也具有一个Looper,主线程所有的任务都是由looper完成。消息循环是由一个线程和一个looper组成,looper对象管理着线程的消息队列;因此,looper不断的从消息队列中抓取消息,然后完成消息指定的任务。
PS: 线程默认情况下,是没有消息循环(Looper)的,在Android中,只有主线程默认就是Looper(消息循环)。在新创建的线程中,使用Looper,要先创建一个Looper才行。
从下面图中了解一下Runnable、Message、MessageQueue、Looper、Handler含义:
(此图来自于其它书籍资料)
将这此含义揉合在一起就是一个消息从发出到执行的整个过程:
(此图来自于其它书籍资料)
从上面这两个图中,我们可以了解到:
1. Runnable和Message压入到MessageQueue中,形成一个消息集合。
2. Looper在不断的循环,不停的在做某一件事,比如:上图中Looper在不停的从MessageQueue中拿出Item,再传递给Handler执行。
3. Handler在不断的去做某一具体的事情,比如:Handler收到一个消息,去解析一个后台返回的数据,再将其更新到UI上。
从上面来看,Handler和Thread从表像上看确实没有直接的关系,但是因为:
1. 每个Thread只能对应一个Looper;
2. 每个Looper只能对应一个MessageQueue;
3. 每个MessageQueue有N个Message;
4. 每个Message最多指定一个Handler来处理;
由此,可以推出Thread和Handler是一对多的关系。而Handler有两方面作用:
1. 处理Message,作为Message处理者。
2. 负责将Message压入MessageQueue中。
四、Message与Handler
Message与Handler是成对出现的,Message是消息,而Handler是消息要完成任务的对象。
消息是Message的一个实例,在实现一个消息时,要同时实现Message类的一些实例变量,
-
- what: 用户定义的Int类型消息代码,用来描述消息。
- obj: 随消息一起发送的用户指定的对象,即消息传递的数据。
- target:完成消息指定任务的目标,即用来完成消息指定任务的对象。
Handler是完成消息或消息指定任务的对象,Handler不仅是完成消息的目标或对象,也是创建和发布消息(Message)的接口。
(图来源于Android权威指南)
- Looper拥有message的消息队列,所以,message必须在Looper上发布或读取。
- 一个Handler仅一个Looper相关联,一个Message也仅与一个目标Handler(message目标)相关联。而Looper拥有消息的整个队列。
在看看下面这个图,
(图来源于Android权威指南)
从上面这个图中,可以看出,有多个Handler与一个Looper相关联,这说明一个Handler的message与另一个Handler的message放于同一个消息队列。
五、Handler使用
1. 使用Handler.obtainMessage(...)方法会从公共循环消息队列中,获取message。
2. 使用Handler.sendToTarget()方法,会方法消息发送给与message相关联的Handler。而Handler会将message放于Looper的消息队列尾部。
3. Looper在消息队列中,获取到特定的消息后,将其发送给消息目标(与之相关联的Handler)去处理。消息一般在Handler(消息目标)的handlerMessage(...)实现方法处理消息指定要完成的任务。一般,要继承Handler基类,覆盖handlerMessage()方法。
六、传递Handler
Handler类的一个实例,可以作为函数参数,传递给其它子线程。
主线程拥有一个Handler和Looper消息循环,在线程中,主线程上创建一个Handler,会自动与主线程的Looper相关联。将主线程创建的Handler传递给另一个子线程,传递出去的Handler始终会与创建它的线程的Looper保持联系。因此,任何已传出的Handler负责处理的消息,都将在主线程的消息队列中处理。
那么,就可以通过这种方式,在子线程中,去更新主线程的事件,数据,或者UI。
七、在新线程中,创建Looper(消息循环)
在主线程中不用创建Looper是因为App启动时,创建主线程中默认创建了Looper,并且一个线程中,只能有一个Looper。存在多个系统会报错。
Looper为什么不会堵塞主线程,提示ANR(application not responding)?
因为,主线程中的Activity和所有事件都是通过Looper执行的。Looper有一个消息队列,在不断的接收事件消息和执行事件。此中的堵塞是指Looper循环不被堵塞,而非Looper堵塞线程。