1. Service 工作状态概述
- Service 分为两种工作状态,一种是启动状态,主要用于执行后台计算;另一种是绑定状态,主要用于其他组件和 Service 的交互
- Service 的这两种工作状态时可以共存的,即 Service 既可以处于启动状态也可以同时处于绑定状态
2. Service 启动过程概述
Service 的启动过程从 ContextWrapper 的
startService()
方法开始:1
2
3public ComponentName startService(Intent service) {
return mBase.startService(service);
}- 从 ContextImpl 的实现可以看出,其大部分操作都是通过 mBase 来实现的,这是一种典型的桥接模式
在 ContextImpl 中,
startService()
方法会调用startServiceCommon()
方法,startServiceCommon()
方法又会通过ActivityManagerNative.getDefault()
这个对象(实际上就是 AMS(ActivityManagerService))来启动一个服务。通过 AMS 来启动服务的行为是一个远程过程调用 RPCAMS 会通过 mService 这个对象来完成 Service 后续的启动过程,mService 对象的类型是 ActiveServices。ActiveServices 是一个辅助 AMS 进行 Service 管理的类,包括 Service 的启动、绑定和停止等
ServiceRecord 描述的是一个 Service 记录,ServiceRecord 一致贯穿整个 Service 的启动过程。
startServiceInnerLocked()
方法并没有完成具体的启动工作,而是把后续的工作交给了bringUpServiceLocked()
方法来处理,在bringUpServiceLocked()
方法中又调用了realStartServiceLocked()
方法在
realStartServiceLocked()
方法中,首先通过app.thread
的scheduleCreateService()
方法来创建 Service 对象并调用其onCreate()
方法,接着再通过sendServiceArgsLocked()
方法来调用 Service 的其他方法,比如onStartCommand()
方法,这两个过程均是 IPC 进程间通信。app.thread
对象是 IApplicationThread 类型,它实际上是一个 Binder,它的具体实现是 ApplicationThread 和 ApplicationThreadNative,ApplicationThread 继承了 ApplicationThreadNative分析 ApplicationThread 的
scheduleCreateService()
方法源码,这个过程和 Activity 的启动过程是类似的,都是通过发送消息给 Handler H 来完成的。H 会接收这个CREATE_SERVICE
消息并通过 ActivityThread 的handleCreateService()
方法来完成 Service 的最终启动ActivityThread 的
handleCreateService()
方法的主要逻辑- 首先通过类加载器创建 Service 的实例
- 然后创建 Application 对象并调用其
onCreate()
方法,当然 Application 的创建过程只会有一次 - 接着创建 ContextImpl 对象并通过 Service 的
attach()
方法建立二者之间的关系,这个过程和 Activity 实际上是类似的,毕竟 Service 和 Activity 都是一个 Context - 最后调用 Service 的
onCreate()
方法并将 Service 对象存储到 ActivityThread 中的一个列表中 - 由于 Service 的
onCreate()
方法被执行了,这也意味着 Service 已经启动了。此外,ActivityThread 中还会通过handleServiceArgs()
方法调用 Service 的onStartCommand()
方法
3. Service 绑定过程概述
和 Service 的启动过程一样,Service 的绑定过程也是从 ContextWrapper 开始的:
1
2
3public boolean bindService(Intent service, ServiceConnection conn, int flags) {
return mBase.bindService(service, conn, flags);
}- 这个过程和 Service 的启动过程是类似的,mBase 同样是 ContextImpl 类型的对象。ContextImpl 的
bindService()
方法最终会调用自己的bindServiceCommon()
方法
- 这个过程和 Service 的启动过程是类似的,mBase 同样是 ContextImpl 类型的对象。ContextImpl 的
ContextImpl 的
bindServiceCommon()
方法的主要逻辑- 首先将客户端的 ServiceConnection 对象转化为
ServiceDispatcher.InnerConnection
对象。之所以不能直接使用 ServiceConnection 对象,这是因为服务的绑定有可能是跨进程的,因此 ServiceConnection 对象必须借助于 Binder 才能让远程服务端回调自己的方法,而 ServiceDispatcher 的内部类 InnerConnection 刚好充当了 Binder 这个角色。ServiceDispatcher 起着连接 ServiceConnection 和 InnerConnection 的作用。这个过程由 LoadApk 的getServiceDispatcher()
方法来完成 - 接着
bindServiceCommon()
方法会通过 AMS 来完成 Service 的具体的绑定过程,这对应于 AMS 的bindService()
方法 - 然后,AMS 会调用 ActiveServices 的
bindServiceLocked()
方法,bindServiceLocked()
方法在调用bringUpServiceLocked()
方法,bringUpServiceLocked()
方法又会调用realStartServiceLocked()
方法。和启动 Service 不同的是,Service 的绑定过程会调用app.thread
的scheduleBindService()
方法
- 首先将客户端的 ServiceConnection 对象转化为
Service 有一个特性,当多次绑定同一个 Service 时,Service 的
onBind()
方法只会执行一次,除非 Service 被终止了