Service 基础生命周期回顾:onCreate、onStartCommand、onDestroy 调用时机与返回标志
在深入前台服务之前,必须清晰掌握普通 Service 的三个核心生命周期方法:onCreate()、onStartCommand()、onDestroy()。前台的启动/停止行为完全基于这些方法,区别仅在于必须绑定一个前台通知。理解调用时机和返回标志,是避免服务被系统意外回收或重启混乱的基石。
| 生命周期方法 | 调用时机 | 调用次数 | 典型用途 |
|---|---|---|---|
onCreate() | 首次通过 startService() 或 bindService() 创建 Service 时 | 仅一次(除非 Service 被销毁后重新创建) | 初始化定时器、线程池、数据库连接、通知渠道等 |
onStartCommand() | 每次调用 startService() 时触发(如果 Service 已创建,跳过 onCreate() 直接进入此处) | 每次 start 都调用 | 处理本次启动的 Intent、执行后台任务 |
onDestroy() | 调用 stopService() 或 stopSelf(),且系统决定真正销毁 Service 之前 | 仅一次 | 释放资源、关闭线程、取消通知、反注册广播 |
关键认知:前台服务与后台服务的生命周期方法完全一致。区别在于前台服务必须调用
startForeground() 并在 onStartCommand() 返回时保持通知可见,但 onCreate/onStartCommand/onDestroy 的调用时机规则不变。
onStartCommand 返回标志详解
onStartCommand() 必须返回一个整型常量,用于告知系统如果该 Service 因内存不足被系统杀死后,系统应该以何种行为恢复它。这是 Android Service 生命周期中极为特殊且常被误解的环节。
| 返回标志 | 整型值 | 行为说明 | 典型场景 |
|---|---|---|---|
START_STICKY | 1 | Service 被杀后系统会尽力重新创建它,并传入 null 的 Intent 调用 onStartCommand()(即不恢复原 Intent) | 持续运行的任务(如音乐播放、位置追踪),无需恢复原始启动参数 |
START_NOT_STICKY | 2 | Service 被杀后系统不会自动重启,除非有新的 startService() 调用 | 一次性任务(如上传单个文件),重启无意义 |
START_REDELIVER_INTENT | 3 | Service 被杀后系统会重新创建服务,并重新投递最后一个未完成的 Intent | 需要确保任务完整执行(如下载队列、支付确认) |
START_STICKY_COMPATIBILITY | 0 | 兼容模式,行为类似 START_STICKY 但不受 startId 序列管理,不推荐使用 | 极低版本兼容(API 5 以下),现代开发应避免 |
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 处理启动 Intent
if (intent != null) {
String action = intent.getAction();
// 根据 action 执行不同任务
}
// 前台服务通常返回 START_STICKY 保证系统重启
return START_STICKY;
}
实践要点:
- 前台服务(Foreground Service)推荐使用
START_STICKY或START_REDELIVER_INTENT,因为前台通知表明用户期望该服务持续运行,系统重启后应尽量恢复。 - 如果服务完全由前台通知驱动且任务可丢弃,可返回
START_NOT_STICKY减少不必要的资源开销。 - 切勿返回
START_STICKY_COMPATIBILITY,该标志在现代 Android 中行为不可预期。
完整生命周期调用顺序示例
以下代码片段展示了在普通 Service 中如何记录所有生命周期方法的调用日志,便于观察调用时机:
public class DemoService extends Service {
private static final String TAG = "DemoService";
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate: 服务创建");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand: 收到启动请求,startId=" + startId);
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy: 服务销毁");
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null; // 未绑定情况
}
}
当依次执行 startService() → stopService() 时,日志输出如下:
D/DemoService: onCreate: 服务创建
D/DemoService: onStartCommand: 收到启动请求,startId=1
D/DemoService: onDestroy: 服务销毁
若连续调用两次 startService(),则 onCreate() 只调用一次:
D/DemoService: onCreate: 服务创建
D/DemoService: onStartCommand: 收到启动请求,startId=1
D/DemoService: onStartCommand: 收到启动请求,startId=2
陷阱提醒:如果 Service 已在运行,
onCreate() 不会再次触发。这也意味着任何需要在 onStartCommand() 中重新初始化的逻辑(如重置定时器)必须写在 onStartCommand() 内部,不能依赖 onCreate() 重复执行。
上图清晰地展示了:当调用 startService() 后,系统首先调用 onCreate()(仅首次),然后每次都会进入 onStartCommand()。该方法的返回值决定了服务被系统杀死后的恢复策略。只有主动调用 stopService() 或 stopSelf() 时才会触发 onDestroy()。