Service生命周期

来源:互联网 发布:python数组转字符串 编辑:程序博客网 时间:2024/05/18 09:14

按照Google 的官方文档里面提到的:“Service是一个应用程序的组件,它能够在后台之行一些耗时较长的操作,并且不提供用户界面。“此外,应用程序组件还能与Service绑定,并与Service进行交互,甚至是进行进程间通信(IPC)。比如,处理网络传输、音乐播放、之行文件I/O,或者与content provider进行交互,都可以在后台运行。

  Service虽然是运行在后台,但是也是运行在主线程上的,任何耗时的操作,需要放到子线程之行。


1 Service 类型

Service有两种基本类型:

Started

  通过在其他组件(比如Activity)startService来启动。一但启动后,就会一直运行在后台,即使启动它的组件(比如Activity)已经被销毁了。一般情况下,是通过这种方式是不会向调用者返回结果的,比较单一。


Bound

  其他组件通过bindService绑定到Service上。bound服务提供了一个客户端/服务器接口,允许组件与Service进行交互、发送请求、获取结果,甚至利用进程间通信(IPC)跨进程之行这些操作。bindService的生命周期与Started不一样。它的生命周期与被绑定的应用程序组件一样。一个Service,允许被多个组件绑定,只有所有的组件解除绑定后,Service才会被销毁。


2 Service 的关键回调方法

1) onStartCommand

  通过startService启动的,便会回调此方法。此后便会在后台一直运行下去。一旦完成工作后,需要调用stopSelf或是stopService来终止这个Service。


2)onBind

  通过bindService绑定的(比如之行IPC),会回调此方法。此时,必须返回一个IBinder来提供一个接口,客户端可以与Service进行通信。 但如果不需要提供绑定,可以返回null。


3)onCreate

  Service第一次创建会被调用,有点类似Activity。可以用来做一次性的配置工作。如果服务已经运行了,则本方法不会被调用。


4)onDestroy

  Service被销毁时,就会调用本方法。服务收到的最后一个回调,可以在这里做一些资源回收,比如线程、已注册的监听器listener和接收器receiver。


3 创建一个Started服务

  started服务在上文已经提到它的启动方法。在传递数据时,可以借助Intent,给Service传递数据。

  在Android 1.6版本及以下,在onStart处理intent数据,从Android 2.0以上,则在onStartCommand里处理。

  一般情况下,你可以扩展两个类来创建Started的Service。如下所示

1)Service

  这是所有服务的基类。记得所有的工作都放在新的子线程来完成。因为Service是运行在主线程的。


2)IntentService

  Service的扩展子类。它使用工作线程来处理所有的启动请求,每次请求都会启动一个线程。如果,服务不需要同时处理多个请求的话,这是最佳的选择。所有的处理工作都在onHandleIntent()里面实现即可,onHandleIntent已经是运行在子线程里面了,可以直接执行一些耗时操作。





备注:

  onStartCommand方法必须返回一个整数值。这个整数值是声明系统在杀死服务之后,应该继续如何运行。(IntentService默认替你处理了这一点,自己无须关心),返回值必须如下几个常量:

START_NOT_STICY

  如果onstartCommand返回后,被系统杀死,则不会再重新创建服务了,除非还是在未发送的intent。当服务不是必须的,并且应用程序能够简单地重启这些未完成的工作时,这是避免服务运行的最安全选项。


START_STICKY

  如果onStartCommand返回后,被系统杀死,则将重新创建服务并再调用onStartCommand,但不会再次传入上一个intent的值,而是null。除非还有启动服务的intent未发送完,那么剩下的intent会继续发送。适用于媒体播放器,它们不执行命令,但需要一直运行并随时待命。


START_REDELIVER_INTENT

  如果onStartCommand返回后,被系统杀死,则会重新创建这个服务,并传入上一个已经传入过的intent,任何未发送完的intent也都会被依次送入。这使用于哪些需要立即恢复工作的活跃服务,比如下载文件。




4 创建一个bound服务

  正如上面提到的,通过bindService可以完成绑定。用于创建一个长期存在的连接。(一般不再允许其他组件通过调用startService再来启动服务)

  当应用程序的activity或者其它组件需要与服务进行交互,或者应用程序某些功能需要暴露给其它应用程序时,这时候,就可以创建一个bound服务,并且通过进程间通信(IPC)来完成。

  要创建一个bound服务,你必须实现onBind回调方法,并返回一个IBinder对象,此对象定义了与服务进行通信的接口。然后其它应用程序组件可以调用bindService()来获得接口并调用服务中的方法。服务只在为绑定的应用程序组件工作时才存活,因此,只要没有组件绑定到服务,系统就会自动销毁服务。



5 在前台运行服务

  前台服务即指那些需要经常被关注的服务,怕内存过低导致被杀。前台服务必须提供一个状态栏通知,并会置于”Ongoing“组下。这意味着只有在服务被终止或者从前台移除之后,此通知才能被解除。

  例如,用服务来播放音乐的播放器就应该运行在前台,因为用户会清楚地知晓它的运行情况。 状态栏通知可能会标明当前播放的歌曲,并允许用户启动一个activity来与播放器进行交互。

  要把你的服务请求为前台运行,可以调用startForeground()方法。此方法有两个参数:唯一标识通知的整数值、状态栏通知Notification对象。例如:


  要从前台移除服务,请调用stopForeground()方法,这个方法接受个布尔参数,表示是否同时移除状态栏通知。此方法不会终止服务。不过,如果服务在前台运行时被你终止了,那么通知也会同时被移除。


6 服务生命周期

  Service 类似于Activity,服务也存在生命周期回调方法,你可以实现这些方法来监控服务的状态变化,并在适当的时机执行一些操作。 如下图所示

1)启动的Service,允许绑定


2)started和bound服务生命周期


  尽管此图把startService()创建的服务和bindService()创建的分开描述了,但请记住,无论启动的方式如何,所有的服务实际上都允许被绑定。 因此,用onStartCommand()启动的服务(客户端调用startService())仍然可以接收onBind()调用(当客户端调用了bindService()时)



原文地址:

《Service 生命周期》

0 0