重识Service
Service是应用程序组件application component,可以运行在后端执行耗时操作。Service没有UI,开始后可持续执行一段时间的操作,即使切换到其他APP后也继续执行。
另外,service运行在主进程之中,它自身不会创建线程或运行在一个独立的进程中,要想service独立运行在一个进程中,需要进行配置。
Service类型
Foreground
前台service是用户可感知的服务。例如音频播放器播放音频。且前台Service必须显示Notification(通知)。前台service即使不与用户交互的情况下依然会运行。
Background
后台service是用户无法直接感知到的服务。例如,对内部存储进行操作经常回事一个后端service。
Bound
绑定service是其他应用程序组件通过调用bindService()方法与Service绑定在一起。一个bound service提供了C/S方式的结构,允许其他组件与service交互,想service发送请求,接收数据,以及跨进程通讯(IPC)。只要其他组件bind了service,service就会运行。且一个service一次可以绑定多个组件,而一旦解绑所有其他组件之后,service就会被销毁(destroy)。
Service与线程(Thread)
Service只是运行在background的一个组件,即使用户不操作情况下,service依然会运行,因此只有在需要时创建并使用service组件。
若程序必须在主线程外执行任务,而用户又需要与应用交互,此时应该在另一个组件中创建一个新线程(thread)。创建线程可以考虑使用java.util.concurrent包下的类或者使用Kotlin协程,而不要直接使用Thread类进行创建。
基础
创建Service,必须继承Service类,并且重写关键的callback方法。
onStartCommand()
其他组件(例如Activity)调用startService()方法调用Service组件运行。一旦onStartCommand()方法运行了,Service会在后台不停地运行。当Service内任务执行完成之后需要主动调用stopSelf()或stopService()来停止Service组件。如果只是绑定Service(Bound Type Service)就不需要实现这个方法。
onBind()
在另外组件中调用bindService()方法来调用这个回调方法。实现了这个方法,就需要返回一个IBinder对象调用bindService()的组件。反之如果不需要返回IBinder对象,可以返回null。
onCreate()
系统在初始创建Service组件时调用此回调方法。onCreate()回调在onStartCommand()和onBind()方法之前执行。若service正在运行,则此回调方法不会被调用。
onDestroy()
系统会在service不被使用和即将销毁service前调用此方法。在这个方法中一般执行释放资源的操作,例如:停止线程,移除监听器或广播接收器等。
组件调用startService()启动Service(onStartCommand()方法被调用),Service会持续运行直到调用stopSelf()或者在其他组件中调用stopService()。
组件调用bindService()来启动Service(onBind()方法调用,onStartCommand()不调用),只要一旦bind就开始执行。当所有组件解绑后,service会被System销毁。
Android系统会在low-memory状态下停止service,并且为前端的Activity获取系统资源。如果service绑定到前端Activity,将降低被系统杀死的可能性。若service声明为foreground service,基本不会被杀死。
创建Service
一个启动的Service是另一个组件调用startService()方法运行的。
Service运行后,其生命周期是独立的,与启动它的组件无直接关联。
应用程序组件通过Intent来调用Service,可以通过Intent来传递Service需要的参数。
Service类是所有services的基类。service默认运行在应用程序的主线程中,因此在service若处理耗时操作时,应该在service中创建一个新的线程来执行任务,避免影响整个应用程序的性能。
运行前台服务(Foreground Service)
forground service是用户可感知且系统在low-memory状态下不会快速销毁的服务。同时foreground service必须在状态栏上显示通知。即通知只能在service停止或者从foreground移除后才能被关闭。