一个Service是没有界面且能长时间运行于后台的应用组件.其它应用的组件可以启动一个服务运行于后台,即使用户切换到另一个应用也会继续运行.另外,一个组件可以绑定到一个service来进行交互,即使这个交互是进程间通讯也没问题.例如,一个aservice可能处理网络事物,播放音乐,执行文件I/O,或与一个内容提供者交互,所有这些都在后台进行.
一个service本质上可有两种表现形式:
Started
一个service在某个应用组件(比如一个activity)调用startService()时就处于"started"状态(注意,可能已经启动了).一旦运行后,service可以在后台无限期地运行,即使启动它的组件销毁了.通常地,一个startedservice执行一个单一的操作并且不会返回给调用者结果.例如,它可能通过网络下载或上传一个文件.当操作完成后,service自己就停止了
Bound
一个service在某个应用组件调用bindService()时就处于"bound"状态.一个boundservice提供一个client-server接口以使组件可以与service交互,发送请求,获取结果,甚至通过进程间通讯进行交叉进行这些交互.一个boundservice仅在有其它应用的组件绑定它时运行.多个应用组件可以同时绑定到一个service,但是当所有的自由竞争组件不再绑定时,service就销毁了.
尽管这个文档是把这两种service分开讲的,但你的service可以在这两种方式下工作.—它可以是started(无限期运行)同时也允许绑定.唯一的简单问题是你是否实现了一对回调方法:onStartCommand()允许组件启动它并且onBind()允许绑定.
不论你是应用是否启动,或绑定到一个服务或两者都做了,任何应用组件都可以使用service(即使从另一个应用),跟任何组件都可以使用activity一样—通过一个Intent启动它.然而,你可以在manifest文件中声明服务为私有,并且阻止另外的应用访问它.这在讲如何于manifest文件中声明service时会详细讲解.
注意:一个service是运行在它所在进程的主线程中的—service不会创建它自己的thread也不会运行于单独的进程(除非你另外指定).这表示,如果你的service想做一些狂耗CPU的工作或阻塞型的操作(比如MP3播放或网络通讯),你必须在service中创建一个新的线程来做那些工作.通过使用一个分离的线程,你将减少"应用没有反应"(ANR)错误并且应用的主线程可以保持activity对用户操作的快速反应.
基础
你应使用一个service还是线程?
一个service是一个在用户不与你的应用交互时依然可以运行于后台的简单组件.所以,只有你需要这样做时才创建一个service.
如果你需要执行的工作不在主线程中,但是只有用户在与你的应用交互时才进行,那么你可能应该创建一个新的线程而不是一个service.例如,如果你想播放一些音乐,但是只在你的activity运行时才播放,你应该在onCreate()中创建一个线程,在onStart()运行这个线程,然后在onStop()中停止它.也可以考虑使用AsyncTask或HandlerThread,来代替传统的线程类.
记住,如果你使用了service,它默认会固定运行于你的应用的主线程,所以你应该在其中创建一个线程来执行耗时或阻塞的操作.
要创建一个service,你必须创建一个Service类(或某个已存在的子类)的子类.在你的实现中,你应覆写一些处理有关service生命期的关键方面的回调方法并且提供一个能让组件绑定到service的机制(如果需要).你应覆写的最重要的回调方法是:
onStartCommand()
系统在其它组件比如activity通过调用startService()请求service启动时调用这个方法.一旦这个方法执行,service就启动并且在后台长期运行.如果你实现了它,你需要负责在service完成任务时停止它,通过调用stopSelf()或stopService().(如果你只想提供绑定,你不需实现此方法).
OnBind()
当组件调用bindService()想要绑定到service时(比如想要执行进程间通讯)系统调用此方法.在你的实现中,你必须提供一个返回一个IBinder来以使客户端能够使用它与service通讯,你必须总是实现这个方法,但是如果你不允许绑定,那么你应返回null.
OnCreate()
系统在service第一次创建时执行此方法,来执行只运行一次的初始化工作(在调用它方法如onStartCommand()或onBind()之前).如果service已经运行,这个方法不会被调用.
OnDestroy()
系统在service不再被使用并要销毁时调用此方法.你的service应在此方法中释放资源,比如线程,已注册的侦听器,接收器等等.这是service收到的最后一个调用.
如果一个组件通过调用startService()启动一个service(最终导致onStartCommand()被调用),之后service会保持运行,直到它通过stopSelf()停止自己或另外的组件调用stopService()停止它.
如果一个组件调用bindService()来创建service(onStartCommand()不会被调用),那么service只是运行在绑定期间.一旦service从所有的客户端解除绑定,系统就会杀了它.
Android系统只在内存很少并且必须为具有用户焦点的actvity釋放资源时才会强制停止一个service.如果service是绑定到具有用户焦点的activity上,那么它很难被杀死,并且如果service被声明为运行于前台(后面将讨论),那么它将永不被杀死,除非,如果这个service启动并且长期运行,那么系统将会降低它在后台任务超时列表中的位置然后这个将变成高度易被杀对象—如果你的service被启动,那么它必须被设计为能优雅地处理被系统重启的操作.如果系统杀死了你的service,它会在资源重新可用时立马重启它(但是依赖于你在onStartCommand()中的返回值).关于系统何时杀死一个service的更多信息,请看:android 进程与线程详解.