Service是一个可以在后台执行长时间运行操作而不使用用户界面的应用组件。组件可以进行绑定到Service,与之进行交互,甚至可以进行进程间通信(IPC)。
服务形式主要分成两种:
启动
应用组件调用startService()方法来启动Service,Service既可以在后台无限运行。这种启动方式是单一的操作,不会将结果进行返回。操作完成后,Service会自动停止。
绑定
当应用组件通过调用 bindService() 绑定到服务时,服务即处于“绑定”状态。绑定服务提供了一个客户端-服务器接口,允许组件与服务进行交互、发送请求、获取结果,甚至是利用进程间通信 (IPC) 跨进程执行这些操作。 仅当与另一个应用组件绑定时,绑定服务才会运行。 多个组件可以同时绑定到该服务,但全部取消绑定后,该服务即会被销毁。
注意
服务在其托管进程的主线程中运行,它既不创建自己的线程,也不在单独的进程中运行(除非另行指定)。 这意味着,如果我们在Service中需要进行耗时或者阻塞主线程的操作,需要在Service开启子线程。通过使用单独的线程,可以降低发生“应用无响应”(ANR) 错误的风险,而应用的主线程仍可继续专注于运行用户与 Activity 之间的交互。
基础知识
主要的回调方法:
- onStartCommand()方法。主要是通过startService来启动的,并且可以利用Intent进行与组件交互或者传递信息。
- onBind()方法。通过bindService()来启动,在此方法的实现中,您必须通过返回 IBinder 提供一个接口,供客户端用来与服务进行通信。请务必实现此方法,但如果您并不希望允许绑定,则应返回 null。
- onCreate()方法。无论是启动形式还是绑定形式,都会调用该方法。并且是第一个调用的回调方法。
- onDestory()方法。主要是用于释放资源
扩展IntentService类
由于大多数服务都不需要启动多个请求,所以使用IntentService类会比较简单
IntentService 执行以下操作:
- 创建默认的工作线程,用于在应用的主线程外执行传递给 onStartCommand() 的所有 Intent。
- 创建工作队列,用于将一个 Intent 逐一传递给 onHandleIntent() 实现,这样您就永远不必担心多线程问题。
- 在处理完所有启动请求后停止服务,因此您永远不必调用 stopSelf()。
- 提供 onBind() 的默认实现(返回 null)。
- 提供 onStartCommand() 的默认实现,可将 Intent 依次发送到工作队列和 onHandleIntent() 实现。
综上所述,您只需实现 onHandleIntent() 来完成客户端提供的工作即可。(不过,您还需要为服务提供小型构造函数。)
扩展Service类
扩展Service类要看是通过哪种形式来启动Service。
- 如果是调用startService()方法来启动,无需去实现onBind()方法,需要去实现onStartCommand()方法。
onStartCommand()方法需要一个整型的返回值。 - 如果是调用bindService()方法,需要去实现onBind()方法,返回一个IBinder接口,用于交互。
停止服务
Service一旦启动就要管理好生命周期以及内存资源的问题。需要去调用stopSelf()或者stopService()方法来停止服务。
但是,如果服务同时处理多个 onStartCommand() 请求,则您不应在处理完一个启动请求之后停止服务,因为您可能已经收到了新的启动请求(在第一个请求结束时停止服务会终止第二个请求)。为了避免这一问题,您可以使用 stopSelf(int) 确保服务停止请求始终基于最近的启动请求。也就说,在调用 stopSelf(int) 时,传递与停止请求的 ID 对应的启动请求的 ID(传递给 onStartCommand() 的 startId) 。然后,如果在您能够调用 stopSelf(int) 之前服务收到了新的启动请求, ID 就不匹配,服务也就不会停止。
为了避免浪费系统资源和消耗电池电量,应用必须在工作完成之后停止其服务。 如有必要,其他组件可以通过调用 stopService() 来停止服务。即使为服务启用了绑定,一旦服务收到对 onStartCommand() 的调用,您始终仍须亲自停止服务。