Service的工作过程
Service的两种状态是可以共存的,它既可以处于启动状态也可以同时处于绑定状态。通过Context的startService方法可以启动一个Service,通过Context的bindService可以绑定的方式启动一个Service。
启动和绑定过程的流程图
Service的启动过程
它的启动过程从ContextWrapper的startService开始
mBase的类型是ContextImpl,在活动的启动过程中我们可以知道活动被创建时通过attach方法将一个ContextImpl对象关联起来,这个ContextImpl对象就是上图代码中的mBase。从ContextWrapper的实现可以看出,其大部分操作都是通过mBase来实现的,在设计模式中这是一种典型的桥接模式。接下来看ContextImpl的startService的实现
在ContextImpl中,startService方法会调用startServiceCommon方法,该方法又会通过ActivityManagerService这个对象来启动一个服务。
AMS的startService方法实现
AMS会通过mServices这个对象来完成Service后续的启动过程,mServices对象的类型是ActiveServices,它是一个辅助AMS进行Service管理的类,包括Service的启动、绑定和停止。ActiveServices的startServiceLocked方法的尾部会调用startServiceInnerLocked方法,startServiceInnerLocked实现如下
ServiceRecord描述的是一个Service记录,它一直贯穿整个Service的启动过程。startServiceInnerLocked方法并没有完成具体的启动工作,而是把后续的工作交给了bringUpServiceLocked方法来处理,在bringUpserviceLocked方法中又调用了realStartServiceLocked方法。
首先通过app.thread的scheduleCreateService方法来创建Service对象并调用其onCreate,接着再通过sendServiceArgsLoked方法来调用Service的其他方法,比如onStartCommand,这两个过程均是进程间通信。app.thread对象是IApplication类型,它实际上是一个Binder,它的具体实现是ApplicationThread和ApplcationThreadNative。因为ApplicationThread继承了ApplicationThreadNative,因此只需要看ApplicationThread对Service启动过程的处理即可,这对应着它的scheduleCreateService
这个过程和活动的启动过程是类似的,都是通过发送消息给Handler H来完成。H会接收CREATE_SERVICE消息并通过ActivityThread的handleCreateService方法来完成Service的最终启动
它主要完成了如下几件事
1.创建Application对象,当然Application的创建只会有一次
2.通过类加载器cl创建Service的实例
3.创建ContextImpl对象并通过Service的attach方法建立二者之间的联系,这个过程的活动实际上是类似的,毕竟Service和Activity都是一个Context
4.最后调用Service的onCreate方法并将Service对象存储到ActivityThread中的一个列表中
这个列表的定义为
由于Service的onCreate被执行,意味着Service已经启动了。除此之外,ActivityThread中还会通过handleServiceArgs方法调用Service的onStartCommand方法
Service的绑定过程
和启动过程一样,Service的绑定过程也是从ContextWrapper开始的
mBase同样是ContextImpl类型的对象。ContextImpl的bindService方法最终会调用自己的bindServiceCommon方法
它主要完成如下两件事情
1.将客户端的ServiceConnection对象转化为ServiceDispatcher.InnerConnection对象。
之所以不能直接使用ServiceConnection对象,因为服务的绑定有可能是跨进程的,因此ServiceConnection对象必须借助于Binder才能让远程服务端回调自己的方法,而ServiceDispatcher的内部类InnerConnection刚好充当了Binder这个角色。那么ServiceDispatcher的作用是连接ServiceConnection和InnerConnection。这个过程由LoadedApk的getServiceDispatcher方法来完成,getServiceDispatcher又会调用getServiceDispatcherCommon
mServices是一个ArrayMap,他存储了一个应用当前活动的ServiceConnection和ServiceDispatcher的映射关系。
在ServiceDispatcher的内部又保存了ServiceConnection和InnerConnection对象。当Service和客户端建立连接后,系统会通过InnerConnection调用ServiceConnection中的onServiceConnected方法,这个过程有可能是跨进程的。当ServiceDispatcher创建好之后,getServiceDispatcher会返回其保存的InnerConnection对象。
接着bindServiceCommon方法会通过AMS来完成Service的具体绑定过程,这对应于AMS的bindService方法
AMS会调用ActiveService的bindServiceLocked方法,它的代码中又会调用bringUpServiceLocked方法
bringUpServiceLocked方法又会调用readlStartServiceLocked方法
它最终通过ApplicationThread来完成Service实例的创建并执行其onCreate。和启动不同的是,它的绑定过程会调用app.thread的scheduleBindService方法,这个过程的实现在ActiveServices的requestServiceBindingLocked方法中
ApplicationThread的一系列以schedule开头的方法其内部都是通过Hnalder H来中转的,对于scheduleBindService来说也是如此
在H内部接收到BIND_SERVICE消息时,会交给ActivityThread的handleBindService方法来处理,在handleBindService方法中,首先根据Service的token取出Service的token取出Service对象,然后调用Service的onBind方法,Service的onBind方法会返回一个Binder对象给客户端使用。原则上来说Service的onBind被调用以后Service就处于绑定状态了,但此时客户端并不知道已经成功连接Service了,所以还必须调用客户端的ServiceConnection中的onServiceConnected,这个过程由AMS的publishService方法来完成。
Service有一个特性,当多次绑定同一个Service时,Service的onBind方法只会执行一次,除非Service被终止了。当Service的onBind执行以后,系统还需要告知客户端,依靠AMS的publishService方法来完成。
它将具体的工作交给了ActiveServices类型的mServices对象来处理。
publishServiceLocked方法核心代码只有一句:c.conn.connected(r.name,service,false),c的类型是ConnectionRecord,c.conn的类型是ServiceDispatcher.InnerConnection,service就是Service的onBind方法返回的Binder对象。
ServiceDispatcher.InnerConnection的定义
它的connected方法又调用了ServiceDispatcher(LoadApk类的内部类)的connected方法
对于Service的绑定过程来说,ServiceDispatcher的mActivityThread是一个Hnadler,其实就是ActivityThread的H,从前面ServiceDispatcher的创建过程来说,mActivityThread不会为null,这样RunConnection就可以经由H的post方法从而运行在主线程中,因此客户端ServiceConnection中的方法只在主线程回调的。
Runconnection定义如下
它的run方法也是简单调用了ServiceDispatcher的doConnected方法,由于ServiceDispatcher内部保存了客户端的ServiceConnection对象,因此它可以很方便地调用ServiceConnection对象的onServiceConnected方法