Android 四大组件分别是 Activity、Service、BroadcastReceiver 和 ContentProvider。
四大组件的运行状态
- 除了 BroadcastReceiver 以外,其他三种组件都必须在 AndroidManifest 中注册,而 BroadcastReceiver 既可以在 AndroidManifest 中注册也可以通过代码动态注册。
- Activity、Service 和 BroadcastReceiver 的调用都需要借助 Intent,而 ContentProvider 却不需要。
- Activity 是一种展示型组件,用于向用户展示界面,可由显式或者隐式 Intent 来触发启动。
- Service 是一种计算型组件,用于在后台执行一系列计算任务。尽管 Service 是用于执行后台计算的,但是它本身是运行在主线程中的,因此耗时的后台计算仍然需要在单独的线程中去完成。Service 组件有两种状态:启动状态和绑定状态。当 Service 处于绑定状态时,外界可以很方便地和 Service 进行通信。
- BroadcastReceiver 是一种消息型组件,用于在不同的组件乃至不同的应用之间传递消息,它工作在系统内部。广播有两种注册方式:静态注册和动态注册。静态注册是在 AndroidManifest 中注册,在应用安装的时候会被系统解析,这种广播不需要应用启动就可以收到相应的广播。动态注册需要通过
Context.registerReceiver()
来注册,通过Context.unRegisterReceiver()
来解除, 这种广播需要应用启动才能注册并接收广播。BroadcastReceiver 组件一般来说不需要停止,它也没有停止的概念。 - ContentProvider 是一种数据共享型组件,用于向其他组件乃至其他应用共享数据。ContentProvider 中的
insert
、delete
、update
和query
方法需要处理好线程同步,因为这几个方法是在 Binder 线程池中被调用的,另外 ContentProvider 组件也不需要手动停止。
Activity 的工作过程
Service 的工作过程
Service 有两种工作状态:一种是启动状态(startService
),主要用于执行后台计算;一种是绑定状态(bindService
),主要用于其他组件和 Service 的交互。需要注意的是,这两种状态是可以共存的。
启动状态
绑定状态
BroadcastReceiver 的工作过程
简单回顾下我们使用广播接收器的过程:
- 继承 BroadcastReceiver 并重写
onReceive
方法。 - 通过 AndroidManifest 静态注册或者通过代码
registerReceiver
动态注册接收器。 - 最后通过 sendBroadcast 来发送广播。
广播的注册过程
广播注册分为静态注册和动态注册,其中静态注册是由 PackageManagerService 来完成整个注册过程,当然其他三大组件也是这样完成注册的。
动态注册过程
发送和接收过程
- 广播的发送有几种类型:普通广播(Normal Broadcast)、系统广播(System Broadcast)、有序广播(Ordered Broadcast)、粘性广播(Sticky Broadcast)和 App应用内广播(Local Broadcast)。
- 从 Android 3.1 开始,处于停止状态的应用无法接受到开机广播。停止状态分为两种情况:一是应用安装后未运行;二是应用被手动或者其他应用强停了。
ContentProvider 的工作过程
- ContentProvider 的
onCreate
要先于 Application 的onCreate
而执行。利用这一特性,我们可以实现一些第三方库的零侵入初始化,开发者只需要添加依赖即可。 - 启动过程:
- 应用启动的入口为 ActivityThread 的
main
方法,main
方法会创建 ActivityThread 实例并创建主线程消息队列。 attach
方法中远程调用 AMS 的attachApplication
方法,并提供 ApplicationThread 用于和 AMS 通信。attachApplication
方法会通过bindApplication
方法和 H 来调回 ActivityThread 的handleBindApplication
方法,这个方法会先创建 Application,再加载 ContentProvider,然后才会回调 Application 的onCreate
方法。- ContentProvider 的
multiprocess
属性决定了 ContentProvider 是否是单例,默认为 false,一般情况下都用单例。当设置为 true 时,每个调用者的进程中都存在一个 ContentProvider 对象。 - ContentResolver 的具体类是 ApplicationContentResolver,当 ContentProvider 所在进程未启动时,第一次访问它的任何一个方法时,都会触发 ContentProvider 的创建以及进程的启动。
- 应用启动的入口为 ActivityThread 的
- 以
query
方法为例的流程图: