Service组件概览学习

前言

作为Android四大组件之一的Service组件是一种可在后台长时间运行而不提供界面的应用组件。Service的一大特点就是可以在后台运行,即使用户切换到其他应用Service也可以继续工作。Service比较典型的应用场景是在后台播放音乐、处理网络事务、处理I/O等。

接下来就来学习下Service组件基础的特性。

Service的属性与启动方式

在讲Service的生命周期前,先看下Service的三种类型以及Service的启动方式。在官方文档中,将Service分为3中类型,分别为:前台服务、后台服务以及绑定服务。而启动方式有两种,分别为启动服务(startService)与绑定服务(bindService)。

Service的类型

前台服务

前台服务的一个条件就是必须显示通知,比如在通知栏中的音乐播放器就是用的前台服务。即使用户不在于应用进行交互,前台服务也会继续运行。

后台服务

顾名思义,后台服务运行在后台,通常用户无法感知Service的存在。

绑定服务

当应用通过bindService()方法启动Service时,Service就是绑定服务。

Service的启动方式

启动服务

如果Service是通过startService()方法启动的,那么Service就是启动服务。通过这种方式启动的Service可以无限期在系统中运行(当然如果系统回收服务资源时,服务也会停止运行)。要停止服务可以调用stopSelf()方法。服务停止后,系统会销毁服务。

绑定服务

如果服务是其他组件通过调用bindService()方法启动的,那么服务就是绑定服务。同时客户端可以通过IBinder接口与服务进行通信。客户端通过unbindService()方法关闭与Service的连接。如果所有连接全部都被关闭,系统就会销毁服务。

这两种启动方式并不是相互排斥的,启动服务时可以同时使用两种启动方式。这个时候在unbindService()前,调用stopSelf()或者stopService()方法不会停止服务。

Service终止行为

终止行为是在Service被终止时的一种行为表现。这种方式是在通过startService()启动服务时,在生命周期方法onStartCommand()返回的整形数决定的。

onStartCommand()中返回的值不同,行为也不同。通常我们会遇到这种情况,在APp进程被系统回收或者通过最近使用任务终止时,我们会看到有些启动的Service会在一段时间后被重新启动。这种现象就是onStartCommand()中的返回值在起作用。

START_NOT_STICKY

如果系统在 onStartCommand() 返回后终止服务,则除非有待传递的挂起 Intent,否则系统不会重建服务。这是最安全的选项,可以避免在不必要时以及应用能够轻松重启所有未完成的作业时运行服务。

根据官方描述,这种返回值在Service被终止时,系统不会重新启动Service。除非重新调用startService()。

START_STICKY

如果系统在 onStartCommand() 返回后终止服务,则其会重建服务并调用 onStartCommand(),但不会重新传递最后一个 Intent。相反,除非有挂起 Intent 要启动服务,否则系统会调用包含空 Intent 的 onStartCommand()。在此情况下,系统会传递这些 Intent。此常量适用于不执行命令、但无限期运行并等待作业的媒体播放器(或类似服务)。

可以看到,当返回START_STICKY时,系统会在某个时间点重启服务,但是重启服务时只会传递一个空信息的Intent。

START_REDELIVER_INTENT

如果系统在 onStartCommand() 返回后终止服务,则其会重建服务,并通过传递给服务的最后一个 Intent 调用 onStartCommand()。所有挂起 Intent 均依次传递。此常量适用于主动执行应立即恢复的作业(例如下载文件)的服务。

和START_STICKY一样,这个返回值也会让系统重建服务。不同的是START_REDELIVER_INTENT在系统重建服务时会将之前的Intent全部依次返回。

除了上面3个经常见到的返回值,还有其他返回值。这里也不一一介绍了。返回值的作用主要就是影响Service的终止与重建的结果。

Service的生命周期

老规矩,先上图:

Service组件概览学习

从图中可以很直观的看出,Service存在两种不同的生命周期。这两种生命周期跟Service的启动方式有关。但在不同之外,也有相同点。那就是Service的启动跟终止都会经历onCreate()跟onDestory()方法。

启动服务的生命周期

第一次启动服务:onCreate()->onStartCommand()

再次启动:只调用onStartCommand()

终止服务:onDestory()

绑定服务的生命周期

第一次启动服务:onCreate()->onBind()

再次启动服务:没有回调产生

终止服务:onUnbind()->onDestory()

两种启动方式同时启动的服务

以启动服务开始

[1] 以启动服务方式启动:onCreate()->onStartCommand()

​ 以绑定服务开始:onBind()

[2] 关闭启动服务:没有回调

​ 关闭绑定服务:onUnbind()->onDestory()

[3]关闭绑定服务:onUnbind();(再次绑定服务:onRebind())

​ 关闭启动服务:onDestory()

以绑定服务开始

[1] 以绑定服务方式启动:onCreate()->onBind()

​ 以绑定服务开始:onStartCommand()

[2] 关闭启动服务:没有回调

​ 关闭绑定服务:onUnbind()->onDestory()

[3]关闭绑定服务:onUnbind();(再次绑定服务:onRebind())

​ 关闭启动服务:onDestory()

总结

在使用某种技术的开始,我们通常是先熟悉这种技术的基本属性和用法。所以在精进技术的时候先从基础知识下手是一种不错方式。对基础知识的熟练掌握可以更加扎实的体现在编写具体代码的过程中。

这里汇总了Service组件经常用到的属性以及一些要点,在我们用到Service时是不可或缺的。