04. Service

185 阅读4分钟

[toc]

Service是什么?

Service 是 Android 中的一种应用组件,用于在后台执行长时间运行的操作,而无需与用户交互或显示 UI。它可以通过 startService() 启动,并在后台持续运行,即使启动它的 Activity 已经被销毁,它仍然可以继续运行。

系统会保持后台服务进程的运行,除非设备内存不足。这时,系统可能会优先终止后台服务进程,以释放资源,确保前台进程和可见进程的正常运行。

后台服务进程适合处理诸如:

  • 播放音乐:例如音乐播放器在后台播放音乐时,用户可能已经关闭了 UI,但音乐仍在播放。
  • 下载文件:后台下载服务,即使用户退出应用,下载仍在继续。

Service启动方式

startService() 启动

  • 启动流程:
    1. 调用 startService(Intent)
    2. 如果服务尚未创建,系统会调用 onCreate()
    3. 系统接着调用 onStartCommand(Intent, int, int),在此处理服务的具体任务。
  • 后续的生命周期:
    • 服务启动后会保持运行状态,即使启动它的组件(如 Activity)被销毁,服务依然继续运行。
    • 直到显式调用 stopService() 或者服务内部调用 stopSelf(),服务才会停止,并触发 onDestroy() 方法。

bindService启动

启动流程

  1. 调用 bindService(Intent, ServiceConnection, int)
  2. 如果服务尚未创建,系统会调用 onCreate()
  3. 接着,系统调用 onBind(Intent),返回一个 IBinder 对象,用于客户端与服务之间的通信。

后续生命周期

  • 当客户端通过 bindService() 绑定到服务时,服务会运行,且绑定关系存在,服务会一直保持活动状态。
  • 如果所有客户端都解除绑定(通过调用 unbindService()),服务将调用 onUnbind(),接着调用 onDestroy(),服务停止。
  • 如果客户端(如 Activity)被销毁,且未解除绑定,服务也会自动停止。

举例:bindService启动

方法Activity 使用 bindService(Intent service, ServiceConnection conn, int flags) 方法与 Service 绑定。

流程

  1. 创建 Intent,指向要绑定的 Service
  2. 创建 ServiceConnection,用于接收 Service 的代理对象。
  3. 调用 bindService() 进行绑定。
  4. 当绑定成功时,Service 会通过回调将代理对象传递给 ServiceConnection,从而获取 Service 的实例。

示例代码

Intent intent = new Intent(this, MyService.class);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);

ServiceConnection 示例

private ServiceConnection serviceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        MyService.MyBinder binder = (MyService.MyBinder) service;
        MyService myService = binder.getService();
        // 可以通过 myService 调用 Service 中的方法
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        // Service 意外断开时的处理
    }
};

小结:

startService() 适用于那些不需要客户端交互的持续性任务,例如后台播放音乐、后台下载文件等。

bindService() 适用于客户端需要与服务交互的场景,例如在 Activity 中获取后台服务的数据等。

Service生命周期

Service有两种生命周期,分别是启动服务和绑定服务。

1. Unbounded Service(启动服务)

这种服务通过调用 startService() 来启动,通常用于在后台执行长时间运行的任务。

生命周期流程:

  • onCreate():当服务第一次启动时调用,执行一次性初始化工作。
  • onStartCommand():每次调用 startService() 时都会触发该方法,这里处理服务的具体任务。服务启动后,会一直保持运行状态,直到显式停止。
  • Service is running:服务处于活动状态,持续运行,除非被调用 stopSelf()stopService() 显式停止。
  • onDestroy():当服务被停止时调用,用于释放资源。

关键点

  • 服务不会自动停止,即使调用 startService() 的组件被销毁,服务依然会运行,直到明确调用 stopSelf()stopService()

2. Bounded Service(绑定服务)

这种服务通过调用 bindService() 来启动,客户端通过绑定与服务交互。

生命周期流程:

  • onCreate():当服务第一次启动时调用,执行一次性初始化工作。
  • onBind():每次客户端通过 bindService() 绑定到服务时调用,返回一个用于客户端与服务通信的 IBinder 对象。
  • Service is running:当至少有一个客户端绑定到服务时,服务处于活动状态。服务会随着所有客户端解除绑定而停止。
  • onUnbind():当所有客户端调用 unbindService() 时,触发该方法,表示最后一个客户端与服务解除绑定。
  • onDestroy():当所有客户端解除绑定且服务不再需要时调用,用于清理资源并销毁服务。

关键点

  • 服务的生命周期取决于是否有客户端绑定。一旦所有客户端解除绑定,服务将被销毁。

总结:

  • Unbounded Service(启动服务):独立于客户端的存在,服务启动后会一直运行,直到显式停止。
  • Bounded Service(绑定服务):服务的生命周期与客户端绑定状态相关,当最后一个客户端解除绑定时,服务会停止。