【学习】Android四大组件启动流程(2)——Service的启动和绑定流程

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方法
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值