Adnroid 四大组件的工作过程
四大组件的运行状态
- Activity 是一种展示型组件,用于向用户直接地展示一个界面,并且可以接收用户的输入信息从而进行交互。
- Service 是一种计算型组件,用于后台执行一系列计算任务。
- BroadcastReceiver 是一种消息型组件,用于在不同的组件乃至不同的应用之间传递消息。
- ContentProvider 是一种数据共享型组件,用于向其他组件乃至其他应用共享数据。
根 Activity 的启动过程
根 Activity 的启动过程一般情况下也可以理解为应用程序的启动过程。
Launcher 请求 AMS 过程
当点击应用程序的快捷图标时,会调用 Launcher.java 的 startActivitySafely 方法。
- startActivitySafely
- 先将 Flag 设置为 Intent.FLAG_ACTIVITY_NEY_TASK,使根 Activity 在新的任务栈中启动。
- 其次,调用 startActivity 方法,此方法在 Activity.java 中实现。
- startActivity
在 startActivity 方法中会调用 startActivityForResult 方法。 - startActivityForResult
其中,调用 Instrumentation(主要用来监控应用程序和系统的交互) 的 execStartActivity 方法。 - execStartActivity
调用 ActivityManager.java 的 getService 方法获取 AMS 的代理对象,接着调用它的 startActivity 方法。 - Android 8.0 之前,通过ActivityManagerNative 的 getDefault 来获取 AMS 的代理对象。
- 现在,这个逻辑封装到了 ActivityManager 中。
AMS 到 ApplicationThread 的调用过程
Launcher 请求 AMS 后,代码逻辑已经进入 AMS 中。
- AMS 的 startActivity
- 其中,return startActivityAsUser()。
- startActivityAsUser
- 判断调用者进程是否被隔离。
- 根据调用者的 UserId,检查其是否有权限。
- 调用 ActivityStarter(7.0新加入的类,它是加载 Activity 的控制类,会收集所有的逻辑来决定如何将 Intent 和 Flag 转换 为 Activity,并将 Activity 和 Task 以及 Stack 相关联) 的 startActivityMayWait。
- startActivityMayWait
- 其中,调用了 startActivityLocked 方法。
- startActivityLocked
- 其中,调用了 startActivity 方法。
- startActivity
- 判断 IApplicationThread 类型的 caller(它指的是 Launcher 所在的应用程序进程的 ApplicationThread 对象) 是否为 null。
- 调用 AMS 的 getRecordForAppLocked 方法得到代表 Launcher 进程的 callerApp 对象(它是 ProcessRecord 类型的,ProcessRecord 用于描述一个应用程序进程)。
- 创建即将要启动的 Activity 的描述类 ActivityRecord(它用来记录一个 Activity 的所有信息),并将它赋值给 ActivityRecord[] 类型的 outActivity,这个 outActivity 会作为接下来的 startActivity 方法的参数传递下去。
- startActivity 方法紧接着调用了 startActivityUnchecked 方法。
- startActivityUnchecked
主要处理与栈管理相关的逻辑。 - 执行 setTaskFromReuseOrCreateNewTask 方法,其内部会创建一个新的 TaskRecord ,用来描述一个 Activity 任务栈。
- 调用 ActivityStackSupervisor 的 resumeFocusedStackTopActivityLocked 方法。
- resumeFocusedStackTopActivityLocked
- 调用 ActivityStack 的 topRunningActivityLocked 方法获取要启动的 Activity 所在栈的栈顶的不是处于停止状态的 ActivityRecord。
- 调用 ActivityStack 的 resumeTopActivityUncheckedLocked 方法。
- resumeTopActivityUncheckedLocked
- 调用 ActivityStack 的 resumeTopActivityInnerLocked 方法。
- resumeTopActivityInnerLocked
- 调用 ActivityStackSupervisor 的 startSpecificActivityLocked 方法。
- startSpecificActivityLocked
- 获取即将启动的 Activity 所在的应用程序进程。
- 判断要启动的 Activity 所在的应用程序进程如果已经运行,则调用 realStartActivityLocked 方法。
- realStartActivityLocked
- 其中的 app.thread 指的是 IApplicationThread,它的实现是 ActivityThread 的内部类 ApplicationThread(它继承了 IAppliactionThread.Stub)。
- app 指的是传入的要启动的 Activity 所在的应用程序进程。
- 因此,app.thread.scheduleLaunchActivity() 指的就是要在目标应用程序进程启动 Activity。
- 当前代码逻辑运行在 AMS 所在的进程(SystemServer 进程)中,通过 ApplicationThread 来与应用程序进程进行 Binder 通信,换句话说,ApplicationThread 是 AMS 所在进程和应用程序进程的通信桥梁。
ActivityThread 启动 Activity的过程
Activity 的工作过程
Activity 的 startActivity() 有好几种重载方式,但最终都会调用 startActivityForResult()。
- startActivityForResult()
调用 Instrumentation 的 execStartActivity()。
mMainThread.getApplicationThread() 这个参数的类型是 ApplicationThread(是 ActivityThread 的一个内部类)。 - execStartActivity()
启动 Activity 真正的实现由 ActivityManagerNative.getDefault()(IActivityManager 类型的 Binder 对象,具体实现是 ActivityManagerService) 的 startActivity() 完成。
checkStartActivityResult() 的作用是检查启动 Activity 的结果。 - startActivity()
由于 ActivityManagerNative.getDefault() 实际上是 AMS,因此启动过程转移到了 AMS 中,来看 AMS 的 startActivity()。
将启动过程转移到了 ActivityStackSupervisor 的 startActivityMayWait(),又经过一些列的调用过程,又将启动过程转移到了 ActivityStack 的 resumeTopActivitiesLocked()。 - resumeTopActivitiesLocked()
调用了 resumeTopActivityInnerLocked() –> ActivityStackSupervisor 的 startSpecificActivityLocked() –> realStartActivityLocked()。 - realStartActivityLocked()
一段重要代码,app.thread.scheduleLaunchActivity()。其中 app.thread 的类型位 IApplicationThread。 - IApplicationThread
它继承了 IInterface 接口,是一个 Binder 类型的接口。其实现者完成了大量和 Activity 以及 Service 的启动/停止相关功能。
实现者是 ActivityThread 中的内部类 AppliactionThread。 - AppliactionThread
它继承了 ApplicationThreadNative。而 ApplicationThreadNative 继承了 Binder 并实现了 IApplicationThread 接口,其内部还有一个 ApplicationThreadProxy 类。
ApplicationThreadNative 是 IApplcationThread 的实现者,由于 ApplicationThreadNative 被系统定义为抽象类,所以 AppliactionThread 就成了 IApplicationThread 最终的实现者。
到此,Activity 的启动过程最终回到了 AppliactionThread 中,AppliactionThread 通过 scheduleLaunchActivity() 来启动 Activity。 - scheduleLaunchActivity()
会发送一个启动 Activity 的消息交由 Handler(名字叫 H) 处理。 - H
从对 “LAUNCH_ACTIVITY” 这个消息的处理可知道,启动过程由 ActivityThread 的 handleLaunchActivity() 来实现,其又调用 performLaunchActivity()。 - performLaunchActivity()
最终完成了 Activity 对象的创建和启动过程,并且 ActivityThread 通过 handleResumeActivity() 来调用被启动 Activity 的 onResume 这一生命周期方法。它主要完成了如下几件事: - 从 ActivityClientRecord 中获取待启动的 Activity 的组件信息
- 通过 Instrumentation 的 newActivity() 使用类加载器创建 Activity 对象
- 通过 LoadedApk 的 makeApplication() 来尝试创建 Application 对象
- 创建 ContextImpl 对象并通过 Activity 的 attach() 来完成一些重要数据的初始化
- 调用 Activity 的 onCreate()
Service 的工作过程
使用一个 Service 分为两种工作状态,并且是可共存的:
- 启动状态:主要用于执行后台计算
- 绑定状态:主要用于其他组件和 Service 的交互
Service 的启动过程
Service 的启动过程从 ContextWrapper 的 startService 开始:
- startService()
调用了 mBase.startService()。mBase 的类型是 ContextImpl 对象,其实现了 ContextWrapper 的大部分操作(桥接模式)。 - startService()
调用了 startServiceCommon() –> ActivityManagerNative.getDefault() 这个对象来启动一个服务(实际上是通过 AMS 来启动服务,这是一个远程过程调用)。
AMS 会通过 mServices 这个对象(类型是 ActivityServices,用以辅助 AMS 进行 Service 管理的类)来完成 Service 后续的启动过程,mServices.startServiceLocked() –> startServiceInnerLocked()。 - startServiceInnerLocked()
ServiceRecord 一直贯穿着整个 Service 的启动过程,描述的是一个 Service 记录。
其把启动的后续工作交给了 bringUpServiceLocked() –> realStartServiceLocked()。 - realStartServiceLocked()
首先通过 app.thread 的 scheduleCreateService() 创建 Service 对象并调用其 onCreate(),接着再通过 sendServiceArgsLocked() 调用 Service 的其他方法。这两个过程均是进程间通信。
接着看 app.thread 对象的具体实现 ApplicationThread 对 Service 启动过程的处理,对应着 scheduleCreateService()。 - scheduleCreateService()
发功消息给 Handler H,H 处理 CREATE_SERVICE 消息,并通过 ActivityThread 的 handleCreateService() 完成 Service 的最终启动。 - handleCreateService()
其主要完成了如下几件事: - 通过类加载器创建 Service 的实例
- 创建 Application 对象并调用其 onCreate,此过程只一次
- 创建 ContextImpl 对象并通过 Service 的 attach() 建立二者之间的关系。、
- 调用 Service 的 onCreate() 并将 Service 对象存储到 ActivityThread 中的一个列表中
Service 的绑定过程
从 ContextWrapper 的 bindService() 开始:
- bindService()
mBase.bindService() –> 最终会调用自己的 bindServiceCommon()。 - bindServiceCommon()
主要完成两件事: - 首先将客户端的 ServiceConnection 对象转化为 ServiceDispatcher.InnerConnection 对象
- 接着通过 AMS 来完成 Service 的具体绑定过程
- AMS 的 bindService()
调用 ActiveServices 的 bingServiceLocked() –> … –> realStartServiceLocked()。 - realStartServiceLocked()
最终通过 ApplicationThread 完成 Service 实例的创建并执行其 onCreate()。
与启动 Service 不同,绑定过程会调用 app.thread 的 scheduleBindService(),方法位于 ActiveServices 的 requestServiceBindingLocked() 中。 - scheduleBindService()
通过 Handler H 来中转,在 H 内部,接收到 BIND_SERVICE 这类消息时,会交给 ActivityThread 的 handleBindService() 处理。 - handleBindService()
首先根据 Service 的 token 取出 Service 对象,然后调用 Service 的 onBind()(会返回一个 Binder 对象给客户端使用)。当多次绑定同一个 Service 时,onBind() 只会执行一次,除非 Service 被终止了。
由于 onBing 是 Service 的方法,客户端并不知道已经成功连接 Service 了,还需调用客户端的 ServiceConnection 中的 onServiceConnected(),这个过程由 ActivityManagerNative.getDefault() 的 publishService() 来完成的。 - publishService()
将具体工作交给了 ActiveServices 类型的 mServices 对象来处理,mServices.publishServiceLocked()。 - publishServiceLocked()
核心代码,c.conn.connected(r.name, service)。其中,c 的类型是 ConnectionRecord,c.conn 的类型是 ServiceDispatcher.InnerConnection,service 就是 onBind() 返回的 Binder 对象。 - ServiceDispatcher.InnerConnection
它的 connected() 调用了 ServiceDispatcher 的 connected()。 - connected()
ServiceDispatcher 的 mActivityThread 是一个 Handler,也就是 ActivityThread 中的 H。mActivityThread.post(new RunConnection(name,service,0))。
RunConnection 经由 H 的 post() 运行在主线程中,因此,客户端 ServiceConnection 中的方法是在主线程被回调的。 - RunConnection
最终调用 ServiceConnection 对象的 onServiceConnected() 完成绑定过程。至于 Service 的停止和解除绑定过程,系统的执行过程是类似的。
BroadcastReceiver 的工作过程
广播的注册过程
广播的注册分为静态注册和动态注册,其中静态注册的广播在应用安装时由系统自动完成注册,具体来说是由 PMS(PackageManagerService)来完成整个注册过程的,除了广播以外,其它三大组件也都是在应用安装时由 PMS 解析并注册的。
动态注册的过程是从 ContextWrapper 的 registerReceiver() 开始的:
- registerReceiver()
mBase.registerReceiver() –> ContextImpl 又调用了自己的 registerReceiverInternal() - registerReceiverInternal()
系统首先从 mPackageInfo 获取 IIntentReceiver 对象,然后再采用跨进程的方式向 AMS 发送广播注册的请求。注册过程是一个进程间通信的过程。
IIntentReceiver 是一个 Binder 接口,具体实现是 LoadedApk.ReceiverDispatcher.InnerReceiver。
ReceiverDispatcher 在构造方法中同时保存了 BroadcastReceiver 和 InnerReceiver,这样当接收到广播时,ReceiverDispatcher 可以方便地调用 BroadcastReceiver 的 onReceive()。 - AMS 的 registerReceiver()
最终会把远程的 InnerReceiver 对象以及 IntentFilter 对象存储起来,这样整个广播的注册过程就完成了。
广播的发送和接收过程
当通过 send() 发送广播时,AMS 会查找出匹配的广播接收者并将广播发送给它们处理。
普通广播的实现,其发送和接收的本质是一个过程的两个阶段,发送开始于 ContextWrapper 的 sendBroadcast(),但它仍然交给了 ContextImpl 处理:
- ContextImpl 的 sendBroadcase()
直接向 AMS 发起了一个异步请求用于发送广播。 - AMS 的 broadcastIntent()
调用了 broadcastIntentLocked()。 - broadcastIntentLocked()
首先控制广播不会发送给已经停止的应用。
在内部,会根据 intent-filter查找出匹配的广播接收者并经过一系列的条件过滤,最终会将满足条件的广播接收者添加到 BroadcastQueue 中,接着 BroadcastQueue 就会将广播发送给相应的广播接收者。 - BroadcastQueue 的 scheduleBroadcastsLocked()
并没有立即发送广播,会发送一个 BROADCAST_INTENT_MSG 类型的消息,BroadcastQueue 收到消息后会调用 processNextBroadcast()。 - processNextBroadcast()
无序广播存储在 mParallelBroadcasts 中,系统会遍历它并通过 deliverToRegisteredReceiverLocked() 将其中的广播发送给它们所有的接收者。 - deliverToRegisteredReceiverLocked()
负责将一个广播发送给一个特定的接收者,内部调用了 performReceiveLocked() 来完成具体的发送过程。 - performReceiveLocked()
app.thread.scheduleRegisteredReceiver()。 - ApplicationThread 的 scheduleRegisteredReceiver()
通过 InnerReceiver 来实现广播的接收。InnerReceiver 的 performReceive() 会调用 LoadedApk.ReceiverDispatcher 的 performReceive()。 - performReceive()
会创建一个 Args 对象并通过 mActivityThread 的 post() 来执行 Args 中的逻辑。
Args 实现了 Runnable 接口。mActivityThread 就是 ActivityThread 的内部类 H。 - Args 的 run()
这时,BroadcastReceiver 的 onReceive() 被执行了,也就是说应用已经接收到广播了。
同时,onReceive() 是在广播接收者的主线程中被调用的。
ContentProvider 的工作过程
当 ContentProvider 所在进程启动时,ContentProvider 会同时启动并发布到 AMS 中,这时,它的 onCreate 要先于 Application 的 onCreate。
当一个应用启动时,入口方法为 ActivityThread 的 main(),main() 是一个静态方法,在其中会创建 ActivityThread 的实例并创建主线程的消息队列,然后在 ActivityThread 的 attach() 中会远程调用 AMS 的 attachApplication() 并将 ApplicationThread 对象提供给 AMS。
- attachApplication()
会调用 ApplicationThread 的 bindApplication(),这是个跨进程的过程。 - bindApplication()
其内逻辑会通过 ActivityThread 中的 mH Handler 切换到 ActivityThread 中去执行,具体的方法是 handleBindApplication。 - handleBindApplication()
其中,ActivityThread 会创建 Application 对象并加载 ContentProvider,然后再调用 Application 的 onCreate()。这时 ContentProvider 就已经启动了。
它的四个方法都是通过 Binder调用的,外界无法直接访问 ContentProvider,它只能通过 AMS 根据 Uri 来获取对应的 ContentProvider 的 Binder 接口 IConentProvider,通过它来访问 ContentProvider 中的数据源。
可通过 android:multiprocess 属性决定 ContentProvider 是否是单实例的,但一般可以简单的认为 ContentProvider 都是单实例的,单实例的启动过程如下:
访问 ContentProvider 需要通过 ContentResolver(抽象类),通过 Context 的 getContentResolver() 获取的实际上是 ApplicationContentResolver 对象。
通过 ContentProvider 的四个方法中任意一个都可触发 ContentProvider 的启动过程,也伴随着所在进程的启动(如未启动)。
query() 中,首先获取 IContentProvider 对象,最终通过 acquireProvider() 获取 ContentProvider:
- ApplicationContentResolver 的 acquireProvider()
直接调用了 ActivityThread 的 acquireProvider()。 - acquireProvider()
会从 ActivityThread 中(通过 mRroviderMap 存储已经启动的 ContentProvider)查找是否已经存在目标 ContentProvider,存在就直接返回。
如果没有 ContentProvider 没有启动,那就发送一个进程间请求给 AMS 让其启动目标 ContentProvider,最后再通过 installProvider() 来修改引用计数。
备注