这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战
前言
Service
是Android
设计四大组件之一,在Android
开发中属于较为重要核心知识点。Service
一般用于驻扎在后台执行一系列计算任务,正是因为工作在后台用户无法直接感知到它的存在。Service
有两种运行模式:启动状态和绑定状态。
启动Service方式
工作状态 | 功能 |
---|---|
启动状态 | 执行一些不在界面上显示的后台运算工作 |
绑定状态 | 和其他组件绑定并和Service交互 |
Service的工作状态也是相对的,两种状态可以共存,既可以和其他组件进行绑定也可以执行后台运算。
- 通过startService启动
Intent intentService = new Intent(context,IntentService.class);
startService(intentService);
复制代码
- 通过bindService启动
Intent intentService = new Intent(context,IntentService.class);
bindService(intentService,serviceConnection,BIND_AUTO_CREATE);
复制代码
生命周期
启动服务
- 第一次启动执行startService():onCreate() -> onStartCommand();
- 第二次Service已存在执行startService()的调用:onStartCommand();
- 执行stopService():onDestory()
绑定服务
- 执行bindService():onCreate() -> onBind();
- 解绑服务bindService(): onUnbind() -> onDestory()
启动过程
Service
和Activity
一样都是继承ContextWrapper
似乎在某些层面上看Service
和Activity
有着某种相似性。一般情况下startService
启动的Service
是运行在App
主进程中。若在AndroidManifest
中对Service
配置android:process
属性,Service
就会启动在单独进程中。
startService
在Activity
中调用startService
方法启动Service
,方法在ContextWrapper
中,具体实现在ContextImpl
。在ContextImpl
内部执行startServiceCommon
方法就会在ActivityManager.getService()
获取AMS
去启动Service
。
/// #ContextWrapper.startService
@Override
public ComponentName startService(Intent service) {
return mBase.startService(service);
}
/// #ContextImpl.startService
@Override
public ComponentName startService(Intent service) {
.....
return startServiceCommon(service,false,mUser);
}
/// #ContextImpl.startServiceCommon
ComponentName cn = ActivityManager.getService().startService(mMainThread.getApplicationThread(),service,service.resolveTypeIfNeeded(getContentResolver()),requireForeground,getOpPackgetName(),getArrtibutionTag(),user.getIndetifier()));
/// #ActiveServices.startServiceLocked
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
throws TransactionTooLargeException {
ServiceLookupResult res = retrieveServiceLocked(service, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false, false);
ServiceRecord r = res.record;
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
}
复制代码
可以知道启动Service
其实是Context
(ContextWrapper
)上下文所具备的能力,在Application
、Activity
和Service
中都是可以调用的,最终都是会走到ContextImpl.startService
。
- ContextImpl.StartService
- ContextImpl.startServiceCommon
- ActivityManager.getService().startService()
- ActivityManagerService.startService()
- ActiveServices.startServiceLocked()
- ActiveServices.startServiceInnerLocked()
- ActiveServices.bringUpServiceLocked()
- ActiveServices.realStartServiceLocked()
(1、2)在当前Context
下向SystemServer
发起启动Service
请求
(3、4、5、6)在SystemServer
进程中处理请求
(7)处理Service
启动核心逻辑
(8)AMS和ActivityThread IPC交互过程,创建Service实例并启动。