Service是Android中四大组件之一,在Android开发中起到非常重要的作用,先来看一下官方对Service的定义:

AServiceis an application component that can perform long-running operations in the background and does not provide a user interface. Another application component can start a service and it will continue to run in the background even if the user switches to another application. Additionally, a component can bind to a service to interact with it and even perform interprocess communication (IPC). For example, a service might handle network transactions, play music, perform file I/O, or interact with a content provider, all from the background.

翻译过来就是:Service(服务)是一个没有用户界面的在后台运行执行耗时操作的应用组件。其他应用组件能够启动Service,并且当用户切换到另外的应用场景,Service将持续在后台运行。另外,一个组件能够绑定到一个service与之交互(IPC机制),例如,一个service可能会处理网络操作,播放音乐,操作文件I/O或者与内容提供者(content provider)交互,所有这些活动都是在后台进行。

Service有两种状态,“启动的”和“绑定”


Started

A service is "started" when an application component (such as an activity) starts it by callingstartService(). Once started, a service can run in the background indefinitely, even if the component that started it is destroyed. Usually, a started service performs a single operation and does not return a result to the caller. For example, it might download or upload a file over the network. When the operation is done, the service should stop itself.

Bound
A service is "bound" when an application component binds to it by callingbindService(). A bound service offers a client-server interface that allows components to interact with the service, send requests, get results, and even do so across processes with interprocess communication (IPC). A bound service runs only as long as another application component is bound to it. Multiple components can bind to the service at once, but when all of them unbind, the service is destroyed.

通过startService()启动的服务处于“启动的”状态,一旦启动,service就在后台运行,即使启动它的应用组件已经被销毁了。通常started状态的service执行单任务并且不返回任何结果给启动者。比如当下载或上传一个文件,当这项操作完成时,service应该停止它本身。


还有一种“绑定”状态的service,通过调用bindService()来启动,一个绑定的service提供一个允许组件与service交互的接口,可以发送请求、获取返回结果,还可以通过夸进程通信来交互(IPC)。绑定的service只有当应用组件绑定后才能运行,多个组件可以绑定一个service,当调用unbind()方法时,这个service就会被销毁了。

另外,在官方的说明文档中还有一个警告:

Caution:A service runs in the main thread of its hosting process—the service doesnotcreate its own thread and doesnotrun in a separate process (unless you specify otherwise). This means that, if your service is going to do any CPU intensive work or blocking operations (such as MP3 playback or networking), you should create a new thread within the service to do that work. By using a separate thread, you will reduce the risk of Application Not Responding (ANR) errors and the application's main thread can remain dedicated to user interaction with your activities.

意思是service与activity一样都存在与当前进程的主线程中,所以,一些阻塞UI的操作,比如耗时操作不能放在service里进行,比如另外开启一个线程来处理诸如网络请求的耗时操作。如果在service里进行一些耗CPU和耗时操作,可能会引发ANR警告,这时应用会弹出是强制关闭还是等待的对话框。所以,对service的理解就是和activity平级的,只不过是看不见的,在后台运行的一个组件,这也是为什么和activity同被说为Android的基本组件。

Service生命周期中的一些方法:



通过这个图可以看到,两种启动service的方式以及他们的生命周期,bind service的不同之处在于当绑定的组件销毁后,对应的service也就被kill了。service的声明周期相比与activity的简单了许多,只要好好理解两种启动service方式的异同就行。

1、生命周期上的区别

执行startService时,Service会经历onCreate->onStartCommand。当执行stopService时,直接调用onDestroy方法。调用者如果没有stopService,Service会一直在后台运行,下次调用者再起来仍然可以stopService。

执行bindService时,Service会经历onCreate->onBind。这个时候调用者和Service绑定在一起。调用者调用unbindService方法或者调用者Context不存在了(如Activity被finish了),Service就会调用onUnbind->onDestroy。这里所谓的绑定在一起就是说两者共存亡了。

多次调用startService,该Service只能被创建一次,即该Service的onCreate方法只会被调用一次。但是每次调用startService,onStartCommand方法都会被调用。Service的onStart方法在API 5时被废弃,替代它的是onStartCommand方法。

第一次执行bindService时,onCreate和onBind方法会被调用,但是多次执行bindService时,onCreate和onBind方法并不会被多次调用,即并不会多次创建服务和绑定服务。

2、调用者如何获取绑定后的Service的方法

onBind回调方法将返回给客户端一个IBinder接口实例,IBinder允许客户端回调服务的方法,比如得到Service运行的状态或其他操作。我们需要IBinder对象返回具体的Service对象才能操作,所以说具体的Service对象必须首先实现Binder对象。

3、既使用startService又使用bindService的情况

如果一个Service又被启动又被绑定,则该Service会一直在后台运行。首先不管如何调用,onCreate始终只会调用一次。对应startService调用多少次,Service的onStart方法便会调用多少次。Service的终止,需要unbindService和stopService同时调用才行。不管startService与bindService的调用顺序,如果先调用unbindService,此时服务不会自动终止,再调用stopService之后,服务才会终止;如果先调用stopService,此时服务也不会终止,而再调用unbindService或者之前调用bindService的Context不存在了(如Activity被finish的时候)之后,服务才会自动停止。

那么,什么情况下既使用startService,又使用bindService呢?

如果你只是想要启动一个后台服务长期进行某项任务,那么使用startService便可以了。如果你还想要与正在运行的Service取得联系,那么有两种方法:一种是使用broadcast,另一种是使用bindService。前者的缺点是如果交流较为频繁,容易造成性能上的问题,而后者则没有这些问题。因此,这种情况就需要startService和bindService一起使用了。

另外,如果你的服务只是公开一个远程接口,供连接上的客户端(Android的Service是C/S架构)远程调用执行方法,这个时候你可以不让服务一开始就运行,而只是bindService,这样在第一次bindService的时候才会创建服务的实例运行它,这会节约很多系统资源,特别是如果你的服务是远程服务,那么效果会越明显(当然在Servcie创建的是偶会花去一定时间,这点需要注意)。

service生命周期也涉及一些回调方法,这些方法都不用调用父类方法,具体如下:

[java] view plain copy
  1. publicclassExampleServiceextendsService{
  2. intmStartMode;//indicateshowtobehaveiftheserviceiskilled
  3. IBindermBinder;//interfaceforclientsthatbind
  4. booleanmAllowRebind;//indicateswhetheronRebindshouldbeused
  5. @Override
  6. publicvoidonCreate(){
  7. //Theserviceisbeingcreated
  8. }
  9. @Override
  10. publicintonStartCommand(Intentintent,intflags,intstartId){
  11. //Theserviceisstarting,duetoacalltostartService()
  12. returnmStartMode;
  13. }
  14. @Override
  15. publicIBinderonBind(Intentintent){
  16. //AclientisbindingtotheservicewithbindService()
  17. returnmBinder;
  18. }
  19. @Override
  20. publicbooleanonUnbind(Intentintent){
  21. //AllclientshaveunboundwithunbindService()
  22. returnmAllowRebind;
  23. }
  24. @Override
  25. publicvoidonRebind(Intentintent){
  26. //AclientisbindingtotheservicewithbindService(),
  27. //afteronUnbind()hasalreadybeencalled
  28. }
  29. @Override
  30. publicvoidonDestroy(){
  31. //Theserviceisnolongerusedandisbeingdestroyed
  32. }
  33. }

关于Service生命周期还有一张比较易懂的图(来源于网络)



另外,这里要说明Service的一个子类,IntentService,首先看下官方文档的说明:

IntentService

This is a subclass ofServicethat uses a worker thread to handle all start requests, one at a time. This is the best option if you don't require that your service handle multiple requests simultaneously. All you need to do is implementonHandleIntent(), which receives the intent for each start request so you can do the background work.


IntentService使用队列的方式将请求的Intent加入队列,然后开启一个worker thread(线程)来处理队列中的Intent,对于异步的startService请求,IntentService会处理完成一个之后再处理第二个,每一个请求都会在一个单独的worker thread中处理,不会阻塞应用程序的主线程,这里就给我们提供了一个思路,如果有耗时的操作与其在Service里面开启新线程还不如使用IntentService来处理耗时操作。而在一般的继承Service里面如果要进行耗时操作就必须另开线程,但是使用IntentService就可以直接在里面进行耗时操作,因为默认实现了一个worker thread。对于异步的startService请求,IntentService会处理完成一个之后再处理第二个。


看下IntentService的具体实现:

[java] view plain copy
  1. publicclassHelloIntentServiceextendsIntentService{
  2. /**
  3. *Aconstructorisrequired,andmustcallthesuperIntentService(String)
  4. *constructorwithanamefortheworkerthread.
  5. */
  6. publicHelloIntentService(){
  7. super("HelloIntentService");
  8. }
  9. /**
  10. *TheIntentServicecallsthismethodfromthedefaultworkerthreadwith
  11. *theintentthatstartedtheservice.Whenthismethodreturns,IntentService
  12. *stopstheservice,asappropriate.
  13. */
  14. @Override
  15. protectedvoidonHandleIntent(Intentintent){
  16. //Normallywewoulddosomeworkhere,likedownloadafile.
  17. //Foroursample,wejustsleepfor5seconds.
  18. longendTime=System.currentTimeMillis()+5*1000;
  19. while(System.currentTimeMillis()<endTime){
  20. synchronized(this){
  21. try{
  22. wait(endTime-System.currentTimeMillis());
  23. }catch(Exceptione){
  24. }
  25. }
  26. }
  27. }
  28. }

关于停止Service,如果service是非绑定的,最终当任务完成时,为了节省系统资源,一定要停止service,可以通过stopSelf()来停止,也可以在其他组件中通过stopService()来停止,绑定的service可以通过onUnBind()来停止service。

关于Service还有很多知识,这里就不再一一列举,可以参考http://developer.android.com/guide/components/services.html

更多相关文章

  1. Android(安卓)SDK下载和更新失败的解决方法
  2. Android应用程序调用系统解锁页面
  3. Android应用程序启动过程源代码分析(4)
  4. Android(安卓)studio2.3.3升级3.1.2坑
  5. Android资源加载过程分析
  6. Android(安卓)使用URL通过浏览器调用android app
  7. 在android获取root权限的方法^_^。
  8. Android应用程序启动过程源代码分析(3)
  9. android WebView java与js相互调用

随机推荐

  1. Android的NDK开发(4)————JNI数据结构
  2. Android:Ping命令测试网络
  3. Android & Android_X86的Git地址
  4. tools for working with android jni
  5. Edittext失去焦点
  6. ScrollView里面放入多个子控件
  7. Android 沿着线绘制文字
  8. ubuntu连接android设备(附最简单方法)(转载
  9. Android JSON Parsing Tutorial
  10. Android 背光流程小结