Service的工作过程

Service启动过程

Service的工作过程_第1张图片
service启动过程
  • Service的启动过程从ContextWrapper的startService方法开始

    public ComponentName startService(Intent service) {
        return mBase.startService(service);
    }
    

    mBase的类型是ContextImpl,在Activity创建时会通过attach方法将ContextImpl对象关联起来,ContextWrapper的大部分操作都是mBase来实现的,这种模式叫桥接模式.

  • 在ContextImpl中,startService方法会调用startServiceCommon方法,而该方法会用过ActivityManagerNative.getDefault()对象来启动一个服务,也就是AMS,通过AMS来启动服务的行为是一个远程过程调用。

  • 在AMS中会通过mServices这个对象完成后续的启动过程,mService对象的类型是ActivityService

    ActivityService:辅助AMS进行Service管理的类。包括Service启动、绑定、停止等。

  • ActivityService方法最后会调用startServiceInnerLocked方法

  • startServiceInnerLocked方法并没有完成具体的启动工作,而是把后续的工作交给了bringUpServiceLocked来处理,在该方法中又调用了realStartServiceLocked方法。

  • realStartServiceLocked方法中(两个过程均是进程通信)

    • 首先是通过app.threadscheduleCreateService方法来创建Service并调用其onCreate

    app.threadIApplicationThread类型,它实际上是一个Binder,具体实现是ApplicationThreadApplicationThreadNative,而前者是继承于后者,因此,只需要看ApplicationThread对Service启动过程的处理即可,对应着scheduleCreateService方法。
    这个过程和Activity的启动过程是类似,通过发送消息给Handler H来完成。H接收CREATE_SERVICE消息并通过handlerCreateService来完成Service的最终启动。

          handlerCreateService方法主要做了这几件事
          
          1.通过类加载器创建Service的实例
          2.创建Application对象并调用其onCreate方法(创建过程只会有一次)
          3.创建ConTextImpl对象并通过Service的attach方法建立二者的关系
          4.最后调用Service的onCreate方法并将Service对象存储到ActivityThread中的一个列表中.
    
  • 接着通过sendServiceArgsLocked方法来调用Service的其他方法,比如onStartCommand(ActivityThread通过handleServiceArgs方法调用Service的onStartCommand方法。)


Service绑定过程

Service的工作过程_第2张图片
service绑定过程
  • 和Service启动过程一样,它的绑定过程也是从ContextWrapper开始的。
public boolean bindService(Intent service, ServiceConnection conn,
           int flags) {
    return mBase.bindService(service, conn, flags);
}
  • mBase同样是ContextImpl类型的对象,mBase的bindService方法最终会调用自己的bindServiceCommon方法

    bindServiceCommon方法主要完成如下两件事:

    1. 将客户端的ServiceConnection对象转化为ServiceDispatcher.IServiceConnection对象。

    之所以不能直接使用ServiceConnection对象是因为服务的绑定可能是跨进程的,因此ServiceConnection对象必须借助Binder才能让远程服务端回调自己的方法,而ServiceDispatcher的内部类IServiceConnection刚好充当了Binder这个角色。

    > ServiceDispatcher起着连接SercviceConnection和InnerConnection的作用,这个过程由LoadedApk的getServiceDispatcher方法来完成
    
    > mServices是一个ArrayMap,它存储了一个应用当前活动的ServiceConnection和ServiceDispatcher的映射关系。
    
    1. bindServiceCommon方法会通过AMS完成Service的具体绑定过程.

    AMS调用ActiveServicesd的bindServiceLocked方法,而该方法再调用bindUpServiceLocked方法,bindUpServiceLocked方法又会调用realStartServiceLocked方法

      > realStartServiceLocked的执行逻辑和启动的逻辑类似,都是通过ApplicationThread来完成Service的创建并执行onCreate方法。
      **和启动Service不同的是**,Service的绑定过程会调用app.thread的scheduleBindService方法,这个过程的实现在ActivityService的requestServiceBindingLocked方法。
      
      ApplicationThread的一系列以schedule开头的方法,内部都是通过Handler H中转的。在H内部接收到BIND_SERVICE这类消息时,会交给ActivityThread的handleBindService方法来处理.在该方法中会根据Service的token取出Service对象,然后调用onBind方法.onBind方法会返回一个Binder对象给客户端使用.原则上此时已经属于绑定状态了,但是**onBind方法是Service的方法,这个时候客户端并不知道已经成功连接了**,所以还必须调用客户端的ServiceConnection中的onServiceConnected(这个过程由ActivityManagerNative.getDefault()的publishService方法来完成的)
    
  • Service多次绑定同一个service,service的onBind方法只会执行一次,除非Service被终止。当Service的onBind执行后,系统还需要告知客户端已经成功连接Service。由AMS的publishService方法实现。

  • AMS的publishService方法将具体的工作交给了ActivityServices类型的mServices对象来处理.在ActiveServices的publishServiceLocked方法核心代码只有一句

c.conn.connected(r.name, service);
 > c的类型是ConnectionRecore,c.conn的类型是ServiceDispatcher.InnerConnection,service就是Service的onBind方法返回的Binder对象。
  • 从InnerConection的connected方法又调用了ServiceDispatcherconnected方法.

    对于Service的绑定过程来说,ServiceDisptchermActivityThread是一个Handler,也就是ActivityThread中的H。
    这样一来RunConnection就可以经过H的post方法从而运行在主线程中,因此客户端ServiceConnection中的方法是在主线程中被回调的。
    RunConnection的run方法简单调用了ServiceDisptcherdoConnected方法,由于ServiceDisptcher内部保存了客户端ServiceConnection对象,因此可以方便调用ServiceConnection对象的onServiceConnected方法。

  • 客户端的onServiceConnected方法执行完毕之后,Service的绑定过程也就分析完成了。

——整理自《Android开发艺术探索》(图片来自网络)

你可能感兴趣的:(Service的工作过程)