02-Service生命周期
Service 生命周期
1. 生命周期路径
Service 的生命周期比 Activity 简单,但更容易出错,因为它可能在用户不可见时运行。
Service 主要有两条生命周期路径:
Started Service:startService() -> onCreate() -> onStartCommand() -> onDestroy()
Bound Service:bindService() -> onCreate() -> onBind() -> onUnbind() -> onDestroy()
如果一个 Service 同时被 start 和 bind,则两套规则会叠加。
2. Started Service 生命周期
启动流程:
flowchart TD
A[startService] --> B{Service 是否已创建}
B -- 否 --> C[onCreate]
B -- 是 --> D[onStartCommand]
C --> D[onStartCommand]
D --> E[Service 运行]
E --> F[stopSelf / stopService]
F --> G[onDestroy]
特点:
onCreate()只在首次创建时调用一次。- 每次调用
startService()都会触发一次onStartCommand()。 - Started Service 不会因为启动它的 Activity 销毁而自动停止。
- 必须调用
stopSelf()或stopService()停止。 - 多次
startService()后,不需要多次stopService(),一次停止请求即可让 Service 停止,但并发处理多个 start 请求时要注意stopSelf(startId)。
3. Bound Service 生命周期
绑定流程:
flowchart TD
A[bindService] --> B{Service 是否已创建}
B -- 否 --> C[onCreate]
B -- 是 --> D[onBind]
C --> D[onBind]
D --> E[Service 运行并与 Client 通信]
E --> F[所有 Client unbindService]
F --> G[onUnbind]
G --> H[onDestroy]
特点:
onBind()返回IBinder,客户端通过它与 Service 通信。- 多个客户端可以同时绑定同一个 Service。
- 对同一个 Service,系统只会在第一个客户端绑定时调用
onBind()创建通信通道,后续客户端通常复用同一个IBinder。 - 当所有客户端都解绑后,如果 Service 没有被 start,它会被销毁。
- Bound Service 不需要像 Started Service 那样主动调用
stopSelf()。
4. 同时 startService 和 bindService
一个 Service 可以同时被启动和绑定:
startService() 让 Service 独立运行
bindService() 让客户端与 Service 通信
这种情况下:
| 操作 | Service 是否停止 |
|---|---|
只调用 unbindService() |
不停止,因为仍处于 started 状态 |
只调用 stopService() |
不一定停止,因为仍有客户端绑定 |
stopService() + 所有客户端 unbindService() |
才会停止 |
Service 内部 stopSelf() + 所有客户端解绑 |
会停止 |
示意图:
flowchart TD
A[startService] --> B[onCreate]
B --> C[onStartCommand]
D[bindService] --> E[onBind]
C --> F[Started 状态]
E --> G[Bound 状态]
F --> H{stopSelf/stopService?}
G --> I{所有客户端 unbind?}
H -- 是 --> J{仍有绑定?}
I -- 是 --> K{仍是 started?}
J -- 是 --> G
J -- 否 --> L[onDestroy]
K -- 是 --> F
K -- 否 --> L[onDestroy]
5. onUnbind 与 onRebind
如果所有客户端解绑,系统会调用:
override fun onUnbind(intent: Intent?): Boolean {
return true
}
如果 onUnbind() 返回 true,后续有客户端再次绑定时,会调用:
override fun onRebind(intent: Intent?) {
super.onRebind(intent)
}
如果返回 false,再次绑定时通常不会调用 onRebind()。
6. 生命周期中的资源清理
Service 中常见资源:
- 子线程、线程池、协程。
- BroadcastReceiver。
- 传感器监听。
- 定位回调。
- Binder 连接。
- MediaPlayer、Camera、Bluetooth 等硬件资源。
必须在 onDestroy() 中清理:
class LocationService : Service() {
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
override fun onDestroy() {
scope.cancel()
locationClient.removeLocationUpdates(callback)
super.onDestroy()
}
}
7. 常见错误
错误一:在 Service 里直接做耗时操作
// 错误:onStartCommand 默认在主线程
Thread.sleep(10_000)
正确做法:
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
serviceScope.launch {
doWork()
stopSelf(startId)
}
return START_NOT_STICKY
}
错误二:绑定后不解绑
bindService() 后必须在合适时机调用 unbindService(),否则可能导致 Service 或 Activity 泄漏。
错误三:认为 Activity finish 后 Started Service 一定停止
Started Service 生命周期独立于启动它的组件。Activity 销毁后,它仍可能继续运行,直到显式停止或系统回收。
8. 面试回答模板
问题:Service 生命周期有哪些?
可以这样回答:
Service 有 Started 和 Bound 两条生命周期。Started Service 通过 startService 启动,首次创建走 onCreate,每次启动走 onStartCommand,需要 stopSelf 或 stopService 停止。Bound Service 通过 bindService 绑定,走 onCreate、onBind,客户端通过 IBinder 通信,所有客户端解绑后如果没有 started 状态就会销毁。如果一个 Service 同时被 start 和 bind,需要 stop 和 unbind 都完成后才会真正销毁。