本文作为阅读官方文档笔记/翻译,原文地址
http://developer.android.com/guide/components/services.html
Service是四大组件(component)之一,它可以负责在后台执行耗时的任务。Service还可以实现跨进程通信(IPC)。Service按照启动方式,可以分为两种形式,分别是
以及1
started
。这篇篇文章主要介绍前者1
bound
Started
一个service可以被其他应用组件(比如activity)通过
方式启动,这种方式通过调用应用组件的1
started
方法。一旦service被启动,它将一直运行,即使启动这个service的组件被销毁了,甚至整个app退出了,这种情况,service往往是被销毁了但是会重新生成。通过“started”方式启动的service,往往只是执行一种操作,而与调用者没有更多的交互通信,比如可以在这种service中执行上传,下载的任务,任务完成后,service需要被终止或者自我终止。1
startService()
Bound
一个service可以被其他应用组件(比如activity)通过
的方式启动,这种方式通过调用应用组件的1
bound
方法,这种方式的启动service提供一种1
bindService()
形式的接口,使service和启动service的组件可以进行通信,另外还可以进行跨进程调用(IPC)。通过1
client-server
方式启动的service,只有在被绑定的状态下才会运行。另外,一个service可以被多个组件绑定,当所有组件解除绑定后,service也将会被销毁。1
bound
The Basics
启动service,你需要创建一个继承自service的类,或者继承现有service实现类,比如IntentService。
service可以通过以上
或1
started
两种方式启动,也可以同时使用以上两种方式。然后重写service部分重要的回调方法。最重要的回调方法有如下几个1
bound
-
onStartCommand(): 当通过startService()的方式启动service时,这个方法就将被调用,并且service将被一直执行下去,任务完成后,你最好调用stopSelf()或者stopService()停止该service。通过bound方式启动service时不需要重写这个方法。
-
onBind(): 通过bindService()方式启动service,你需要在onBind()返回一个IBinder实例,如果不想绑定service,那么这个方法返回null即可。
-
onCreate(): 这个方法会在service被首次创建时执行,它在onStartCommand()以及onBind()之前执行,当service是被重启的,或者已经被启动过,那么方法将不会被执行。这个方法适合执行一些初始化的事件。
-
onDestroy(): 当service被销毁,你应该在这里回收资源,比如thread,监听器,广播接受者等等。
service在系统资源很紧张的情况下会被回收,但是如果service绑定着一个处于前台的
,那么它被回收的概率会降低,如果一个service被声明为1
activity
的,那么被回收的概率基本为0.1
foreground
通过
方式启动的1
startService
,虽然可能会被回收,但是也会被重启,所以我们应该处理这个重启的流程,另外,service的重启和1
service
的返回值有紧密的关系,这一点后面会提及。1
onStartCommand()
在manifest中声明service
声明方式如下
关于声明service时的
和1
android:enabled="true"
两个属性,这里不描述。接下来讲述启动1
android:exported="true"
。1
service
Creating a Started Service
一个
方式启动的1
started
,通过调用1
service
,然后会执行1
startService()
方法。调用1
onStartCommand()
时可以传入一个1
startService
,这个1
Intent
会被传递到1
Intent
方法,所以可以借助这个1
onStartCommand()
传递数据给1
Intent
。1
service
方式启动的1
started
会一直在后台运行,所以当1
service
的任务执行完之后,需要处理好销毁回收工作,它可以通过调用1
service
自我关闭,也可以是其他组件调用1
stopSelf()
来终止1
stopService()
。1
service
这里将的’service’会在后台一直运行,是指启动
的组件被销毁了甚至整个app退出了,1
service
可以自动重启,1
service
默认情况下,会在声明的
1service
的进程的
1application
上运行。所以如果在
1main thread
中执行阻塞性的任务,需要启动一个线程。
1service
建立
时,你可以继承自1
service
和1
Service
1
IntentService
-
Service:
如果继承自这个类,那么执行阻塞任务时,需要另外启动线程。1
service
-
IntentService:这个类是对
类的封装,它处理了启动线程的流程,你只需要将你的阻塞任务放在1
service
方法中即可。这个类可以处理同时发起的多个请求,并在所有请求处理完之后自动销毁1
onHandleIntent()
,然后如果继续发起请求,则将再次启动1
service
,这里说的发起请求,就是1
service
方法启动1
startService()
。1
service
其实IntentService的源码很短,可以看一下
从以上代码可以看出IntnetService主要是借助HandlerThread,将线程编程可以不断处理任务的looper线程。然后你可以不断往IntentService发送请求,知道所有请求处理完毕,IntentService才会被销毁。
在以上代码的
中,我们可以看到处理任务的最后一行代码1
Handler
,这里1
stopSelf(msg.arg1);
就是1
msg.arg1
中的1
onStartCommand
,当新的请求来临,这个1
startid
会被更新,只有’msg.arg1’是最新的1
startid
时,才会销毁1
startid
,所以避免了有新请求没被处理时,1
service
就被销毁,同时,当所有请求被处理完后,1
service
就被销毁.IntentService的微妙之处就在这里。1
service
如果你启动一个
,而且执行的任务不需要同时启动多个线程一起执行,那么使用I1
service
是最方便的。同理,如果你需要在1
ntentService
中启动多个线程同时执行任务,那么就只能使用1
service
类了。这时你要做的事情就放在1
Service
类中的1
Service
方法。1
onStartCommand()
方法的返回值觉得了’service’被销毁后如何重建,它的返回值及对应功能如下:1
onStartCommand()
* START_NOT_STICKY:不重建
。1
service
* START_STICKY:重建
,但是不保存1
service
,调用1
Intent
。1
onStartCommand()
* START_REDELIVER_INTENT:重建’
,保存1
service
,调用1
Intent
。1
onStartCommand()
以上的解析是不考虑有pending intents的情况,
Starting a Service
通过’started’方式启动service很简单,如下
传入数据可以借用
,返回结果可以借用广播的机制。1
intent
Running a Service in the Foreground
这种方式启动service,将会弹出一个不能关闭的通知,这种需求经常见于音乐播放器,你可以借助这个通知,在上面做一些操作,比如音乐播放器的下一首,暂停等等。
为了实现这个功能,可以在onStartCommand()中执行如下代码