考察内容:
service启动有哪几种方式?service启动过程中主要流程有哪些?service启动过程涉及哪些参与者,通信过程是怎样的?Service启动原理用startService启动Service:@OverrIDepublic Componentname startService(Intent service) { return startServiceCommon(service, mUser);}Componentname startServiceCommon(Intent service, ...){ Componentname cn = ActivityManagerNative.getDefault() .startService(mMainThread.getApplicationThread(), service, ...); return cn;}
AMS中的处理:
Componentname startService(IApplicationThread caller, Intent service, ...){ Componentname res = mServices.startServiceLocked(caller, service, ...); return res;}
根据intent 查询service Record对象:
每个应用端的Service在AMS中都对应一个ServiceRecore对象
Componentname startServiceLocked(Intent service, ...){ ServiceLookupResult res = retrIEveServiceLocked(service, ...); ServiceRecord r = res.record; ... //查到ServiceRecord之后new了一个StartItem并加到pendingStart里面, //为后面调用onStartCommand准备 r.pendingStart.add(new ServiceRecord.StartItem(r, ...)); ... return startServiceInnerLocked(smap, service, r, ...);}Componentname startServiceInnerLocked(ServiceMap smap, Intent service, ...){ bringUpServiceLocked(r, service.getFlags(), callerFg, false);}final String bringUpServiceLocked(ServiceRecord r, ...){ if(r.app != null && r.app.thread != null) { //如果Service已经启动了,就调用下面这个函数, //它将触发应用端的onStartCommand sendServiceArgsLocked(r, ...); return null; } //Service还没启动的情况: ProcessRecord app = mAm.getProcessRecordLocked(procname, ...); if(app != null && app.thread != null){ //如果Service所在的进程已经启动了,真正启动Service //r.app就是在下面这个函数中设置的 realStartServiceLocked(r, app, execInFg); return null; } //Service所在进程没有启动或者虽然已经启动但还没就绪的情况: if(app == null){ //app进程还没启动,启动进程 app = mAm.startProcessLocked(procname, ...); } if(!mPendingServices.contains(r)){ //把ServiceRecord加到pending列表里面,等待进程启动后再处理 mPendingServices.add(r); } ...}
进程启动的流程图:
boolean attachApplicationLocked(IApplicationThread thread, ...) { ... mServices.attachApplicationLocked(app, processname); ... return true;}//处理pending的Serviceboolean attachApplicationLocked(ProcessRecord proc, ...){ for(int i = 0; i < mPendingServices.size(); i++){ sr = mPendingServices.get(i); ... mPendingServices.remove(i--); //对每一个pending的service调用realStartServiceLocked函数真正启动service realStartServiceLocked(sr, proc, ...); } ...}voID realStartServiceLocked(ServiceRecord r, ProcessRecord app, ...){ r.app = app; ... //向应用端发起IPC调用,应用收到后就会创建Service,执行应用里的onCreate回调 //参数r其实是一个binder对象: final class ServiceRecord extends Binder{} //这是要存在应用端的,应用端有一个用来保存service对象的map,这里的r就是key app.thread.scheduleCreateService(r, r.serviceInfo, ...); ... //触发应用端Service的onStartCommand sendServiceArgsLocked(r, ...);}
应用端是如何处理AMS发过来的CreateServicd请求的:private voID handleCreateService(CreateServiceData data){ //先拿到loadedApk LoadedApk packageInfo = getPackageInfoNoCheck(...); //加载Service类,并通过newInstance调用其构造函数,从而获得Service对象 Service service = (Service)cl.loadClass(data.info.name).newInstance(); //给这个Service创建一个Context对象 ContextImpl context = ContextImpl.createAppContext(this, ...); //获取Application,这个application是在应用启动的时候创建的 Application app = packageInfo.makeApplication(flase, ...); //给service赋予上下文 service.attach(context, this, ...); //执行Service的生命周期 service.onCreate(); mServices.put(data.token, service); ...}mServices是一个map:ArrayMap<IBinder, Service>
private final voID sendServiceArgsLocked(ServiceRecord r, ){ while(r.pendingStarts.size() > 0){ //取出每一个pending的startItem StartItem si = r.pendingStarts.remove(0); ... //向应用端发起IPC调用 r.app.thread.scheduleServiceArgs(r, ...); }}
AMS是如何触发应用端Service的onStartCommand的AMS调用r.app.thread.scheduleServiceArgs(r, …)后,应用端的处理:
public final voID scheduleServiceArgs(IBinder token, ...) { //封装了一个ServiceArgsData对象 ServiceArgsData s = new ServiceArgsData(); ... //丢到应用的主线程去处理 sendMessage(H.SERVICE_ARGS, s);}//应用端主线程的处理:private voID handleServiceArgs(ServiceArgsData data) { //首先从mServices中把Service对象取出来。mService是一个map,其中: //key就是AMS中的ServiceRecord的对象 //value就是应用端的Service对象 //data.token就是AMS中的ServiceRecord对象 Service s = mServices.get(data.token); if(s != null){ ... //调用Service的onStartCommand s.onStartCommand(data.args, data.flags, data.startID); ... }}
总结Service启动的流程:AMS端:先看Service启动了没有:如果启动了就直接发指令,让应用端执行onStartCommand()如果Service没有启动,就看它所在进程启动了没有:如果已经启动,就去启动Service,等Service启动了之后再发送指令让其执行onStartCommand如果进程没有启动就去启动进程,等进程启动后再启动Service
应用端:
先创建Service对象再赋予上下文最后调用生命周期onCreate()用bindService启动Service启动Service还有另一种情况:bindService的时候带上BIND_auto_CREATE标记
int bindServiceLocked(IApplicationThread caller, ...){ ... if((flags & Context.BIND_auto_CREATE) != 0){ //如果带上BIND_auto_CREATE标记 bringUpServiceLocked(s, ...); } ...}
binderService和startService的区别:binderService不会触发应用端的onStartCommand函数因为binderService没有把ServiceRecord加到mPendingStart队列中回归:说说service的启动原理service启动有几种方式?a) startService
b) bindService带BIND_auto_CREATEservice启动过程主要流程有哪些?
a)AMS端:
1)先看Service启动了没有:如果启动了就直接发指令,让应用端执行onStartCommand()
2)如果Service没有启动,就看它所在进程启动了没有:如果已经启动,就去启动Service,等Service启动了之后再发送指令让其执行onStartCommand
3)如果进程没有启动就去启动进程,等进程启动后再启动Service
b)应用端:
1)先创建Service对象
2)再赋予上下文
3)最后调用生命周期onCreate()
a)参考下图:点赞收藏分享文章举报menghaocheng发布了119 篇原创文章 · 获赞 28 · 访问量 10万+私信 关注 总结
以上是内存溢出为你收集整理的【Android话题-5.1应用相关】说说service的启动原理全部内容,希望文章能够帮你解决【Android话题-5.1应用相关】说说service的启动原理所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)