Foreground Service 生命周期:四个关键方法
今天我们来聊聊 Foreground Service 的生命周期。
说白了,就是系统会在什么时候调用你写的那些回调方法。
我刚开始学 Android 时,总以为 Service 和 Activity 差不多。
后来发现,差远了。尤其是 Foreground Service,它有自己的脾气。
一个典型的 Foreground Service,它的生命周期主要围绕四个方法:
onCreate()onStartCommand()onBind()onDestroy()
这四个方法,就是 Service 的“生老病死”。
你想想看,搞懂了它们的调用时机和职责,写出来的 Service 才稳。
onCreate:Service 的“出生证”
onCreate() 在 Service 第一次被创建时调用。
注意,是“第一次”。如果 Service 已经存在,再次启动它就不会再调用了。
这个方法最适合做什么?
- 初始化全局变量
- 创建通知渠道
- 准备线程池或数据库连接
我个人习惯把通知的 NotificationChannel 创建逻辑放在这里。
因为 onCreate 在整个 Service 生命周期里只执行一次,非常适合做这种“一次性”的初始化工作。
onCreate 里直接调用 stopSelf(),阻止 Service 继续运行。
典型代码结构:
@Override
public void onCreate() {
super.onCreate();
// 创建通知渠道
createNotificationChannel();
// 初始化线程池
executorService = Executors.newFixedThreadPool(4);
// 记录日志
Log.d(TAG, "Service 已创建");
}
onStartCommand:任务的“发令枪”
这才是 Foreground Service 的核心战场。
每次调用 startForegroundService() 或 startService(),onStartCommand 都会被触发。
这意味着,它可以被多次调用。嗯,这点很重要。
来看方法签名:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 你的任务逻辑
return START_STICKY;
}
三个参数里,intent 携带启动指令,flags 表示重启标志,startId 是本次启动的唯一标识。
返回值?这里有三种选择,我当年踩过不少坑:
| 返回值 | 行为 | 适用场景 |
|---|---|---|
START_STICKY |
Service 被杀死后,系统会尝试重建,并传入 null Intent 调用 onStartCommand | 需要持续运行,但不依赖启动参数的后台任务 |
START_NOT_STICKY |
Service 被杀死后,系统不会自动重启,直到有新的显式启动请求 | 任务完成后不希望被系统无故重启的场景 |
START_REDELIVER_INTENT |
Service 被杀死后,系统会重建并重新传递最后一次的 Intent | 必须处理上一个任务的场景,比如下载文件 |
onStartCommand 里做了个网络请求,结果系统把 Service 杀了,通知也掉了,用户以为 App 崩了。
后来改成
START_REDELIVER_INTENT 并配合 Foreground Service 的通知重建逻辑,问题才解决。
所以,选对返回值真的很关键。
onBind:绑定的“桥梁”
这个方法在绑定 Service 时调用,也就是其他组件通过 bindService() 连接时。
对于 Foreground Service 来说,onBind 用的其实不多。因为大部分时长任务都不需要频繁交互。
但如果你是做音乐播放器、导航这类需要双向通信的场景,onBind 就很重要了。
它返回一个 IBinder 对象,客户端可以通过这个对象调用 Service 里的方法。
@Override
public IBinder onBind(Intent intent) {
// 返回 Binder 实例
return new LocalBinder();
}
我一般只在需要实时反馈进度的时候才用绑定。
比如大文件上传,客户端需要知道上传百分比。
这时候绑定 Service 比用广播靠谱得多。
onDestroy:体面的“谢幕”
Service 结束时的清理工作,全看这个方法了。
系统会在以下情况调用 onDestroy:
- 调用
stopSelf()或stopService() - 系统需要回收内存,强制杀死 Service
注意:系统强杀时,onDestroy 可能不会被执行。这点要有心理准备。
@Override
public void onDestroy() {
super.onDestroy();
// 关闭线程池
if (executorService != null) {
executorService.shutdown();
}
// 取消通知
stopForeground(STOP_FOREGROUND_REMOVE);
// 释放资源
Log.d(TAG, "Service 已销毁");
}
我曾经在 onDestroy 里忘记调用 stopForeground,结果 Service 死了,通知栏还挂着。
用户点通知,APP 直接崩。嗯,这种错误太低级了,大家引以为戒。
生命周期流程图
下面这张图,把整个生命周期串起来了。我建议你多看几遍,理解每个方法之间的流转关系。
onCreate做一次性的初始化onStartCommand处理每次启动的任务逻辑onBind按需实现,绑定通信onDestroy做好资源清理工作
牢记每个方法的调用时机,你的 Foreground Service 才能稳定运行。