Service 是一种可在后台执行长时间运行操作而不提供界面的应用组件。服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行。此外,组件可通过绑定到服务与之进行交互,甚至是执行进程间通信 (IPC)。例如,服务可在后台处理网络事务、播放音乐,执行文件 I/O 或与内容提供程序进行交互。
启动方式
- startService
- bindService
生命周期
- onCreate
- onStartCommand
- onBind
- onDestroy
onStartCommand
执行时机
通过startService启动会执行此方法
返回值
- START_NOT_STICKY:被杀后不重启
- START_STICKY:被杀后重启,会调用onStartCommand,但是intent是null。默认返回这个值
- START_STICKY_COMPATIBILITY:被杀后重启,不会调用onStartCommand。只有targetSdkVersion < 5才会默认返回这个值
- START_REDELIVER_INTENT:被杀后重启,会调用onStartCommand,会传递最后一个intent
onBind
执行时机
通过bindService启动会执行此方法
返回值
IBinder:通过binder机制实现方法调用
FAQ
- service生命周期在哪个线程执行?
在UI线程执行。service的生命周期都是由ActivityManagerService&ActiveServices控制,他们通过binder通知ApplicationThread改变生命周期,ApplicationThread收到消息之后发送handler消息去执行service的生命周期方法
- service生命周期有超时时间吗?是多少?
有。非前台service限制20s,前台service限制20s*10。
- 一次startService一定对应一次onStartCommand吗?
是的。可能ActiveServices一次发送多个启动任务,ApplicationThread收到之后会依次发送消息去处理。
- onStartCommand的startId来源
启动的Service对应一个ServiceRecord。ServiceRecord的lastStartId记录上次的启动id。每次启动会调用ServiceRecord.makeNextStartId来返回下一个startId。startId从1开始递增。
- onStartCommand的返回值作用原理
ActivityThread.handleServiceArgs执行service的onStartCommand方法,并把返回值通过ActivityManager.getService().serviceDoneExecuting最终回调到ActiveServices. serviceDoneExecutingLocked。在此方法里边根据参数决定是否移除ServiceRecord的相应StartItem和设置ServiceRecord.stopIfKilled属性
- 一次bindService一定对应一次onBind吗?
不是一一对应的。只有service初次绑定才会调用onBind方法,之后ActiveServices会使用记录的IBinder来“返回”给IServiceConnection。
- context销毁之后自动触发unBindService的原理
以actvitiy为例,ActivityThread.handleDestroyActivity -> ContextImpl.scheduleFinalCleanUp -> ActivityThread.scheduleContextCleanUp -> ContextImpl.performFinalCleanUp -> LoadedApk.removeContextRegistrations。在LoadedApk.removeContextRegistrations会移除尚未取消注册的广播接收器或者尚未取消绑定的service。同时会打印错误日志,例如 * has leaked ServiceConnection * that was originally bound here
- 检测connection断开
被动回调 | ServiceConnection.onServiceDisconnected | IBinder.DeathRecipient.binderDied |
---|---|---|
应用范围 | 通过binderService获得的binder | 任意binder |
主动unbind | 不调用 | 不调用 |
remote process killed | 调用 | 调用 |
因为context销毁被动unbind | 不调用 | 不调用 |
主动检测 | IBinder.pingBinder | IBinder.isBinderAlive | 其他自定义Binder方法 |
---|---|---|---|
正常值 | true | true | 正常 |
异常值 | false | false | android.os.DeadObjectException |
- 连接池
一个service智能提供一个binder,但是可以通过这个binder提供获取其他binder的能力,避免创建多个service
- 如何反向调用?
提供方法允许客户端注册binder,即可通过客户端注册的binder调用客户端方法
附-时序图
start service

stop service

bind & unbind service

网友评论