Android Service生命周期详解
引言
应用程序组件有一个生命周期——一开始android实例化他们响应意图,直到结束实例被销毁。在这期间,他们有时候处于激活状态,有时候处于非激活状 态;对于活动,对用户有时候可见,有时候不可见。组件生命周期将讨论活动、服务、广播接收者的生命周期——包括在生命周期中他们可能的状态、通知状态改变 的方法、及这些状态的组件寄宿的进程被终结和实例被销毁的可能性。
上篇android开发之旅:组件生命周期(一)讲解了论活动的生命周期及他们可能的状态、通知状态改变的方法。本篇将介绍服务和广播接收者的生命周期:
服务生命周期
广播接收者生命周期
1、服务生命周期
一个服务可以用在两个方面:
它可以启动且允许一直运行直到有人停止它,或者它自己停止。在这种模式,通过调用context.startservice()启动服务及通过调用 context.stopservice()停止服务。服务也可以通过调用service.stopself()或 service.stopselfresult()停止自己。仅需要调用一次stopservice()停止服务,而不管调用 startservice()了多少次。
通过使用相关接口可以编程地操作服务。客户端建立与service对象的一个连接及使用该连接调入服务。连接通过调用 context.bindservice()建立,通过调用context.unbindservice()关闭。多个客户端可以绑定到同一个服务。如果 服务尚未启动,bindservice()可以选择启动它。
这两种模式并不是完全分离的。你可以绑定到一个用startservice()启动的服务。例如,一个后台音乐服务可以通过使用定义了音乐播放的 intent对象调用startservice()启动。直到后来,用户可能想对播放器做一些控制或者获取当前歌曲的一些信息,一个活动将调用 bindservice()与服务建立连接。在这种情况下,实际上直到最后一个绑定关闭stopservice()并不会停止。
像活动一样,一个服务也有生命周期方法,你可以执行监视它的状态改变。但是比活动的生命周期方法更少,只有三个且它们是公有的(public)而不是受保护的(protected)(说明:活动的生命周期方法是protected的):
void oncreate()
void onstart(intent intent)
void ondestory()
通过这三个方法,你可以监视服务生命周期的两个嵌套循环:
服务的整个生命时间(entire lifetime),从调用oncreate()到相应地调用ondestory()。像一个活动一样,服务在oncreate()中做一些初始设置,且 在中释放所有的资源。例如,一个音乐播放服务可以在oncreate()中创建线程,然后在ondestory()中停止线程。
服务的活跃生命时间(active lifetime),从调用onstart()开始。这个方法传递参数是传送给startservice()的intent对象。音乐服务将打开intent,了解播放哪个音乐并且开始播放。
没有相应的回调方法,因为服务停止没有onstop()方法。
startservice()和ondestory()被所有服务调用,不管是通过context.startservice()启动还是通过 context.bindservice()启动的。然而,onstart()仅被通过startservice()启动的服务调用。
如果一个服务允许别的绑定到它,有一些额外的回调方法来实现它:
ibinder onbind(intent intent)
boolean onunbind(intent intent)
void onrebind(intent intent)
onbind()回调传递的参数是传给bindservice()的intent对象,onunbind()回调传递的参数是传给 unbindservice()的intent对象。如果服务允许绑定,onbind()返回客户端与服务交互的通信通道。onunbind()方法可以 要求调用onrebind(),如果一个新的客户端连接到服务。
下图解释了服务的回调方法。虽然,它分离了由startservice()启动的服务和由bindservice()启动的服务,记住任何服务,无论 它怎么启动的,都可能允许客户端绑定到它,因此任何服务可能接收onbind()和onunbind()调用。
可以发现第一次startservice时,会调用oncreate和onstart,在没有stopservice前,无论点击多少次 startservice,都只会调用onstart。而stopservice时调用ondestroy。再次点击stopservice,会发现不会 进入service的生命周期的,即不会再调用oncreate,onstart和ondestroy。
而onbind在startservice/stopservice中没有调用。
需要注意一个问题,当activity退出的时候,sercvice并不会停止,此时我们可以再进入activity重新绑定,当这时候service 就会调用onrebind()方法,但是调用onrebind()方法的前提是先前的onunbind()方法执行成功,但是使用 super.onunbind(intent)是执行不成功的,这时候我们要手动的使其返回true,再次绑定时rebind()就会执行。否则,如果退 出时不显示的指定onunbind()为成功的话(为false),那么重新启动此activity来绑定服务时,service的onbind()方法 和onrebind都不会执行,但是serviceconnection方法确一定会回调了。这说明在service中的onbind()方法不同于 onstart()方法不能被重复调用。
2、广播接收者生命周期
一个广播接收者有一个回调方法:void onreceive(context curcontext, intent broadcastmsg)。当一个广播消息到达接收者是,android调用它的onreceive()方法并传递给它包含消息的intent对象。广 播接收者被认为仅当它执行这个方法时是活跃的。当onreceive()返回后,它是不活跃的。
有一个活跃的广播接收者的进程是受保护的,不会被杀死。但是系统可以在任何时候杀死仅有不活跃组件的进程,当占用的内存别的进程需要时。
这带来一个问题,当一个广播消息的响应时费时的,因此应该在独立的线程中做这些事,远离用户界面其它组件运行的主线程。如果onreceive()衍 生线程然后返回,整个进程,包括新的线程,被判定为不活跃的(除非进程中的其它应用程序组件是活跃的),将使它处于被杀的危机。解决这个问题的方法是 onreceive()启动一个服务,及时服务做这个工作,因此系统知道进程中有活跃的工作在做。
ps:service 类两种启动方法:
• context.startservice()
• context.bindservice()
1. 在同一个应用任何地方调用 startservice() 方法就能启动 service 了,然后系统会回调 service 类的 oncreate() 以及 onstart() 方法。这样启动的 service 会一直运行在后台,直到 context.stopservice() 或者 selfstop() 方法被调用。
另外如果一个 service 已经被启动,其他代码再试图调用 startservice() 方法,是不会执行 oncreate() 的,但会重新执行一次 onstart() 。
2. 另外一种 bindservice() 方法的意思是,把这个 service 和调用 service 的客户类绑起来,如果调用这个客户类被销毁,service 也会被销毁。用这个方法的一个好处是,bindservice() 方法执行后 service 会回调上边提到的 onbind() 方发,你可以从这里返回一个实现了 ibind 接口的类,在客户端操作这个类就能和这个服务通信了,比如得到 service 运行的状态或其他操作。如果 service 还没有运行,使用这个方法启动 service 就会 oncreate() 方法而不会调用 onstart()。
总结:
1. startservice()的目的是回调onstart()方法,oncreate() 方法是在service不存在的时候调用的,如果service存在(例如之前调用了bindservice,那么service的oncreate方法已经调用了)那么startservice()将跳过oncreate() 方法。
2. bindservice()目的是回调onbind()方法,它的作用是在service和调用者之间建立一个桥梁,并不负责更多的工作(例如一个service需要连接服务器的操作),一般使用bindservice来绑定到一个现有的service(即通过startservice启动的服务)。
由于service 的onstart()方法只有在startservice()启动service的情况下才调用,故使用onstart()的时候要注意这点。