0%

四大组件的工作过程(三):Service 的工作过程

1. Service 工作状态概述

  • Service 分为两种工作状态,一种是启动状态,主要用于执行后台计算;另一种是绑定状态,主要用于其他组件和 Service 的交互
  • Service 的这两种工作状态时可以共存的,即 Service 既可以处于启动状态也可以同时处于绑定状态

2. Service 启动过程概述

  • Service 的启动过程从 ContextWrapperstartService() 方法开始:

    1
    2
    3
    public ComponentName startService(Intent service) {
    return mBase.startService(service);
    }
    • 从 ContextImpl 的实现可以看出,其大部分操作都是通过 mBase 来实现的,这是一种典型的桥接模式
  • 在 ContextImpl 中,startService() 方法会调用 startServiceCommon() 方法,startServiceCommon() 方法又会通过 ActivityManagerNative.getDefault() 这个对象(实际上就是 AMS(ActivityManagerService))来启动一个服务。通过 AMS 来启动服务的行为是一个远程过程调用 RPC

  • AMS 会通过 mService 这个对象来完成 Service 后续的启动过程,mService 对象的类型是 ActiveServices。ActiveServices 是一个辅助 AMS 进行 Service 管理的类,包括 Service 的启动、绑定和停止等

  • ServiceRecord 描述的是一个 Service 记录,ServiceRecord 一致贯穿整个 Service 的启动过程。startServiceInnerLocked() 方法并没有完成具体的启动工作,而是把后续的工作交给了 bringUpServiceLocked() 方法来处理,在 bringUpServiceLocked() 方法中又调用了 realStartServiceLocked() 方法

  • realStartServiceLocked() 方法中,首先通过 app.threadscheduleCreateService() 方法来创建 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 的最终启动

  • ActivityThreadhandleCreateService()方法的主要逻辑

    1. 首先通过类加载器创建 Service 的实例
    2. 然后创建 Application 对象并调用其 onCreate() 方法,当然 Application 的创建过程只会有一次
    3. 接着创建 ContextImpl 对象并通过 Service 的 attach() 方法建立二者之间的关系,这个过程和 Activity 实际上是类似的,毕竟 Service 和 Activity 都是一个 Context
    4. 最后调用 Service 的 onCreate() 方法并将 Service 对象存储到 ActivityThread 中的一个列表中
    5. 由于 Service 的 onCreate() 方法被执行了,这也意味着 Service 已经启动了。此外,ActivityThread 中还会通过 handleServiceArgs() 方法调用 Service 的 onStartCommand() 方法

3. Service 绑定过程概述

  • 和 Service 的启动过程一样,Service 的绑定过程也是从 ContextWrapper 开始的:

    1
    2
    3
    public boolean bindService(Intent service, ServiceConnection conn, int flags) {
    return mBase.bindService(service, conn, flags);
    }
    • 这个过程和 Service 的启动过程是类似的,mBase 同样是 ContextImpl 类型的对象。ContextImpl 的 bindService() 方法最终会调用自己的 bindServiceCommon() 方法
  • ContextImpl 的 bindServiceCommon() 方法的主要逻辑

    1. 首先将客户端的 ServiceConnection 对象转化为 ServiceDispatcher.InnerConnection 对象。之所以不能直接使用 ServiceConnection 对象,这是因为服务的绑定有可能是跨进程的,因此 ServiceConnection 对象必须借助于 Binder 才能让远程服务端回调自己的方法,而 ServiceDispatcher 的内部类 InnerConnection 刚好充当了 Binder 这个角色。ServiceDispatcher 起着连接 ServiceConnection 和 InnerConnection 的作用。这个过程由 LoadApkgetServiceDispatcher() 方法来完成
    2. 接着 bindServiceCommon() 方法会通过 AMS 来完成 Service 的具体的绑定过程,这对应于 AMS 的 bindService() 方法
    3. 然后,AMS 会调用 ActiveServices 的 bindServiceLocked() 方法,bindServiceLocked() 方法在调用 bringUpServiceLocked() 方法,bringUpServiceLocked() 方法又会调用 realStartServiceLocked() 方法。和启动 Service 不同的是,Service 的绑定过程会调用 app.threadscheduleBindService() 方法
  • Service 有一个特性,当多次绑定同一个 Service 时,Service 的 onBind() 方法只会执行一次,除非 Service 被终止了

-------------------- 本文结束感谢您的阅读 --------------------