1.Service的生命周期
1). 被启动的服务的生命周期:如果一个Service被某个Activity 调用 Context.startService 方法启动,那么不管是否有Activity使用bindService绑定或unbindService解除绑定到该Service,该Service都在后台运行。如果一个Service被startService 方法多次启动,那么onCreate方法只会调用一次,onStart将会被调用多次(对应调用startService的次数),并且系统只会创建Service的一个实例(因此你应该知道只需要一次stopService调用)。该Service将会一直在后台运行,而不管对应程序的Activity是否在运行,直到被调用stopService,或自身的stopSelf方法。当然如果系统资源不足,android系统也可能结束服务。
2). 被绑定的服务的生命周期:如果一个Service被某个Activity 调用 Context.bindService 方法绑定启动,不管调用 bindService 调用几次,onCreate方法都只会调用一次,同时onStart方法始终不会被调用。当连接建立之后,Service将会一直运行,除非调用Context.unbindService 断开连接或者之前调用bindService 的 Context 不存在了(如Activity被finish的时候),系统将会自动停止Service,对应onDestroy将被调用。
3). 被启动又被绑定的服务的生命周期:如果一个Service又被启动又被绑定,则该Service将会一直在后台运行。并且不管如何调用,onCreate始终只会调用一次,对应startService调用多少次,Service的onStart便会调用多少次。调用unbindService将不会停止Service,而必须调用 stopService 或 Service的 stopSelf 来停止服务。
4). 当服务被停止时清除服务:当一个Service被终止(1、调用stopService;2、调用stopSelf;3、不再有绑定的连接(没有被启动))时,onDestroy方法将会被调用,在这里你应当做一些清除工作,如停止在Service中创建并运行的线程。
2.启动流程- startService
通过bindService启动Service
1.bindService启动的服务和调用者之间是典型的client-server模式。调用者是client,service则是server端。service只有一个,但绑定到service上面的client可以有一个或很多个。这里所提到的client指的是组件,比如某个Activity。
2.client可以通过IBinder接口获取Service实例,从而实现在client端直接调用Service中的方法以实现灵活交互,这在通过startService方法启动中是无法实现的。3.bindService启动服务的生命周期与其绑定的client息息相关。当client销毁时,client会自动与Service解除绑定。当然,client也可以明确调用Context的unbindService()方法与Service解除绑定。当没有任何client与Service绑定时,Service会自行销毁。
onStartCommand方法的返回值:
onStartCommand方法执行时,返回的是一个int型。
这个整型可以有三个返回值:START_NOT_STICKY、START_STICKY、START_REDELIVER_INTENT
START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand方法后,服务被异常kill掉,系统不会自动重启该服务。
START_STICKY:如果Service进程被kill掉,保留Service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建Service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到Service,那么参数Intent将为null。
START_REDELIVER_INTENT:重传Intent。使用这个返回值时,系统会自动重启该服务,并将Intent的值传入。
started服务与bind服务的区别:
区别一:生命周期
通过started方式的服务会一直运行在后台,需要由组件本身或外部组件来停止服务才会以结束运行
bind方式的服务,生命周期就要依赖绑定的组件
区别二:参数传递
started服务可以给启动的服务对象传递参数,但无法获取服务中方法的返回值
bind服务可以给启动的服务对象传递参数,也可以通过绑定的业务对象获取返回结果
在客户端绑定一个服务的步骤:
(1)实现ServiceConnection抽象类。实现过程中,必须重写一下两个回调方法:
onServiceConnected() 和服务绑定成功后,系统会调用这个方法来发送由服务的onBind()方法返回的IBinder对象
onServiceDisconnected() 当服务异常终止时会调用(如服务崩溃或被杀死时)。注意,在客户端解除绑定时不会调用该方法。
(2)调用bindService()方法来传递ServiceConnection类的实现;
(3)当系统调用你的onServiceConnected()回调方法时,你就可以开始使用接口中定义的方法来调用服务了
(4)调用unbindService()方法断开与服务的链接。
注:bindService()和unbindService()方法都是Context类中的方法。
Service 和 Thread
1.
Service其实是运行在主线程里的
2.Android的后台就是指,它的运行是完全不依赖UI的。即使Activity被销毁,或者程序被关闭,只要进程还在,Service就可以继续运行。比如说一些应用程序,始终需要与服务器之间始终保持着心跳连接,就可以使用Service来实现。
扩展:
Service既然是运行在主线程里,在这里一直执行着心跳连接,难道就不会阻塞主线程的运行吗?当然会,但是我们可以在Service中再创建一个子线程,然后在这里去处理耗时逻辑就没问题了。
3.既然在Service里也要创建一个子线程,那为什么不直接在Activity里创建呢?这是因为Activity很难对Thread进行控制,当Activity被销毁之后,就没有任何其它的办法可以再重新获取到之前创建的子线程的实例;而且在一个Activity中创建的子线程,另一个Activity无法对其进行操作。但是Service就不同了,所有的Activity都可以与Service进行关联,然后可以很方便地操作其中的方法,即使Activity被销毁了,之后只要重新与Service建立关联,就又能够获取到原有的Service中Binder的实例。因此,使用Service来处理后台任务,Activity就可以放心地finish,完全不需要担心无法对后台任务进行控制的情况。
参考博文:
http://blog.csdn.net/todo_/article/details/51097453
IntentService的作用:
当我们需要这样一次性完成的任务时,就可以使用IntentService来完成。
1)新建一个MyIntentService类,继承自IntentService,并重写父类的onHandleIntent()方法,
2)在清单文件中对服务进行注册服务
3)在MainActivity里面加入启动IntentService的逻辑