Android Framework 面试系列(六)Service 启动原理

409 阅读3分钟

在 Android 中,Service 主要有两种启动方式,分别是通过 startService() 方法启动和通过 bindService() 方法启动。

startService 和 bindService 启动服务的区别

区别startServicebindService
生命周期的区别onCreate() -> onStartCommand()(onStart()方法已过时) -> onDestory()onCreate() -> onBind() -> onUnbind() -> onDestory()
运行的区别一旦服务开启跟调用者(开启者)就没有任何关系了。 开启者退出了,开启者挂了,服务还在后台长期的运行。bind 的方式开启服务,绑定服务,调用者挂了,服务也会跟着挂掉。
是否可以调用服务里面的方法开启者不能调用服务里面的方法。绑定者可以调用服务里面的方法。

我们也可以同时使用 startService() 和 bindService() 来启动一个服务,这样服务既可以独立运行,又可以与启动组件进行交互。当需要停止服务时,需要同时调用 stopService() 和 unbindService()。

注意:多次 startService ,不会重复的执行 onCreate(), 而是会调用 onStart() 和onStartCommand();多次调用 bindService,不会执行任何生命周期方法。

startService 的启动流程

image.png

startService 的启动流程如上图所示。可以看到 startService 的启动流程 和 Activity 的启动流程其实差不多,区别主要是方式的调用。

下面介绍一下完整的调用逻辑:

  1. App 进程通过 ActivityManagerProxy 代理,调用到 AMS 的 startService 方法开启 Service 的启动流程
  2. AMS 的 startService 方法会检测 Service 进程是否存在。如果存在,会调用 realStartServiceLocked 直接执行图中的步骤 6、7、8;如果不存在,则会调用 startProcessLocked 方法启动进程(Activity 启动流程中,也是通过 startProcessLocked 创建进程的)
  3. zygote 通过 fork 创建 Service 进程,之后反射调用 ActivityThread.main 方法,再创建 ApplicationThread 与 AMS 通信。AMS 收到 ATTACH_APPLICATION_TRANSACTION 命令后,执行 attachApplicationLocked 方法,该方法会做两件事:1. 通过 ApplicationThreadProxy 回调 Service 进程,让其创建 Application;2. 调用 realStartServiceLocked 方法开始启动 Service。(该步骤中,除了 attachApplicationLocked 会启动 realStartServiceLocked 之外,其他流程都和 Activity 启动流程一样)
  4. realStartServiceLocked 方法会通过 ApplicationThreadProxy 发送 SCHEDULE_CREATE_SERVICE_TRANSACTION 命令。
  5. ApplicationThread 收到命令后,会发送消息 H.CREATE_SERVICE。Handle 收到该消息后,会调用 ActivityThread 的 handleCreateService 方法创建 Service。

bindService 的启动流程

image.png

bindService 的启动流程如上图所示。bindService 流程可以分为启动服务和绑定服务两步,其中启动服务流程和 startService 的流程一样,因此这里只介绍绑定的流程。

  1. App 进程通过 ActivityManagerProxy 代理,调用到 AMS 的 bindService 方法开启 Service 的绑定流程。其中 bindService 方法需要我们传入 LoadedApk 对象。该对象是 Apk 文件在内存中的表示。 Apk 文件的相关信息,诸如 Apk 文件的代码和资源,甚至代码里面的 Activity,Service 等组件的信息我们都可以通过此对象获取。
  2. 如果服务不存在,会通过 startService 来完成启动的流程
  3. 启动完成后,会调用 requestServiceBindingLocked,它会调用 ApplicationThreadProxy 的scheduleBindService 方法
  4. ApplicationThread 的 scheduleBindService 方法会发送消息 H.BIND_SERVICE。Handle 收到该消息后,会调用 ActivityThread 的 handleBindService 方法。
  5. 在handleBindService方法中,对未绑定服务的,先后调用Service的onBind方法和AMS的publishService方法;对已绑定服务的,先后调用Service的onRebind方法和AMS的serviceDoneExecuting方法。

参考