Service 详解
2026/8/23大约 2 分钟
Service 详解:启动方式与绑定方式
Service 是 Android 四大组件之一,用于在后台执行不提供 UI 的长时间任务。
一、Service 的两种使用方式
1. 启动式(startService)
// 启动
startService(Intent(this, DownloadService::class.java))
class DownloadService : Service() {
override fun onBind(intent: Intent): IBinder? = null
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
// 执行后台任务
return START_STICKY // 被杀死后自动重建
}
}生命周期:onCreate → onStartCommand → ... → onDestroy特点:不返回结果给调用方,任务完成后需自行 stopSelf()
2. 绑定式(bindService)
val connection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, binder: IBinder?) {
val myBinder = binder as MyService.MyBinder
myBinder.startWork()
}
override fun onServiceDisconnected(name: ComponentName?) {}
}
bindService(intent, connection, Context.BIND_AUTO_CREATE)生命周期:onCreate → onBind → onUnbind → onDestroy特点:可与 Service 通信,最后一个客户端解绑时销毁
二、前台服务(Foreground Service)
Android 8.0+ 后台服务限制,长时间任务必须使用前台服务并显示通知:
val notification = NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("下载中")
.setSmallIcon(R.drawable.ic_download)
.build()
startForeground(1, notification)注意
- Android 12+ 启动前台服务需声明权限
FOREGROUND_SERVICE - 特殊类型(定位、媒体播放等)还需声明
FOREGROUND_SERVICE_LOCATION等
三、AIDL 跨进程通信(IPC)
当 Service 运行在独立进程时(android:process=":remote"),需要 AIDL 传递自定义对象:
// IRemoteService.aidl
interface IRemoteService {
int getPid();
void basicTypes(int anInt, long aLong, boolean aBoolean);
}进程通信方式对比:
| 方式 | 适用场景 | 特点 |
|---|---|---|
| Binder(AIDL) | 跨进程调用方法 | 高效、支持双向 |
| Messenger | 简单消息传递 | 基于 Handler,串行 |
| ContentProvider | 数据共享 | 适合结构化数据 |
| 广播 | 全局通知 | 单向、低频 |
四、面试高频追问
startService与bindService能否同时使用?如何停止?- Service 在子线程执行任务会 ANR 吗?如何规避?
IntentService与普通 Service 的区别?- 前台服务在 Android 12+ 的限制?
📖 进阶阅读:AIDL 跨进程通信 | Binder 机制详解