概述

1、当用户在与当前应用程序不同的应用程序时,Service可以继续在后台运行。

2、Service可以让其他组件绑定,以便和它交互并进行进程间通信。

3、Service默认运行在创建它的应用程序的主线程中。

Service的使用主要是因为应用程序里面可能需要长时间地运行一些任务但是又不需要用户界面或者应用程序本身需要对外提供一些函数给其他的应用程序调用。每一个Service实体类必须相应地在它的包中的AndroidManifest.xml有一个<service> 配置节的声明。Services可以用 Context.startService() 或Context.bindService()来启动。

下面我们将会涉及到几个主题:

1、什么是Service?

2、Service的生命周期

3、进程生命周期

什么是Service?

很多Android的初学者都对Service抱有浓浓的疑惑,Service到底是什么,但是似乎更多的问题是Service到底不是什么?

  • Service不是一个独立的进程。Service不像他的名字所暗示的,它没有自己独立的进程;除非另外指定,Service运行在跟应用程序相同的进程中,并且他是应用程序进程的一部分。
  • Service不是一个线程。但也不是说Service就运行在界面主线程(Main Thread)中( Android中为了避免应用程序没有响应的错误)。

其实Service非常简单,它主要有两个特性:

  • 它是一种应用程序跟系统进行沟通的机制,告诉系统有一些任务要在后台运行(即在用户使用应用程序的时候)。我们可以对应地调用Context.startService()让系统运行Service,Service会一直运行,直到Service本身或者其他人显式地停止它。
  • 它是一个应用程序对外(其他应用程序)暴露函数接口的机制。我们可以对应地调用Context.bindService()来运行,这样子其他的应用程序就可以长时间地跟Service连接,进行一些交互。

在一个Service组件被创建的时候,系统做的工作其实就是在主线程上实例化Service组件,然后调用Service的onCreate()还有其他Service的回调函数而已。也就是说,可以认为系统除了调用一下Service的函数,其他什么都不会再做了,如果你想要运行什么长时间的任务,比如从网络上下载文件,那么跟以前一样,你需要自己写一个线程,当然是在Service内对应的函数中。

不过正因为Service本身如此简单,我们可以自由定义Service,使之与外界进行一些简单或者复杂的交互。我们可以将Service视为本地Java对象,进行直接的方法调用(具体的示例见Local Service Sample),也可以通过AIDL提供一个完全的远程接口。

Service的生命周期

Service是由Android系统进行调度的。如果有人调用Context.startService(),系统就会将Service取回(有必要的时候创建它,并调用它的onCreate()方法)然后调用它的onStartCommand(Intent, int, int) 方法,使用客户端提供的参数。这时候,Service会继续运行运行直到Context.stopService() or stopSelf()被调用。注意:我们可以多次调用Context.startService()不会发送嵌套调用(尽管会有多次onStartCommand()的响应),所以不管Service多少次被启动,它都只会在一次Context.stopService() 或stopSelf()的调用中被停止。然而,service可以使用它的stopSelf(int)方法来保证自己不会被停止,直到启动它的intents被处理完。

对于一个启动的服务(started Service)有两种操作模型,这决定了它们不同的运行方式,而运行方式由它们的OnStartCommand()函数的返回值决定。START_STICKY适用于一个服务需要被明确地指定启动或停止的情况。而while START_NOT_STICKY 或START_REDELIVER_INTENT使用于一个服务需要一直运行直到处理完它们收到的命令。

客户端也可以使用Context.bindService() 去取得与一个Service的长连接。它同样会创建一个Service,如果Service没有运行(调用onCreate()来创建),但不会调用onStartCommand()。客户端将会接收从service的onBind(Intent)方法返回的IBinder对象,从而客户端就可以调用service上的方法了。只要客户端和service的连接一建立,service就会一直保持运行状态(无论客户端是否有保存service的IBinder引用)。通常IBinder返回的是一个用aidl写好了的复杂接口。

一个service可以同时被启动和绑定。在这种情况下,系统会保持一个带有 Context.BIND_AUTO_CREATE 标识的service一直运行只要他被启动或者有一个或多个连接跟这个服务绑定着。一旦没有被启动和连接,service的onDestroy()就会被调用然后service就会被终止。在onDestroy()方法返回前,所有的线程和资源都应该被清理掉。

Process Lifecycle

前面我们讲到,Service其实是运行在寄居在应用程序的进程当中的,也就是说当应用程序的进程被销毁的时候,Service也就被销毁了。当然,Android系统会尽力保证带有Service的应用程序进程存活尽可能长的时候,只要进程中有Service已经启动或者有别的客户端需要使用着Service的服务。当Android系统内的内存不足,需要杀死一些进程来释放内存时,在下面情况中,线程的优先级会因为Service而增高,进而减少被系统回收的可能性:

  • 如果进程中的Service正在执行onCreate(), onStartCommand(), 或 onDestroy()方法,那么这个进程就会变成前台处理(foreground process)进程,进而能够保证进程不会被回收。
  • 如果一个Service被启动了,那么他的宿主进程就会被系统认为比当前用户正在使用的的应用程序的进程更不重要,但比其他的后台进程更重要。因为通常用户当前只使用一小部分进程(也就是用户看得见的进程),这意味着Service所在的进程不应该被回收掉,除非系统内存极度缺乏。
  • 如果一个客户端(Client)跟Service绑定,那么这个Service的宿主进程会被系统认为跟客户端进程是同等重要的,也就是,如果一个客户端程序对用户是可见的(也就是正在被使用),那么Service自身也会被认为是可见的。
  • 已经开始运行了的Service可以使用startForeground(int, Notification) API将当前进程放到前台状态(Foreground state),这样系统就会认为他是用户想要使用的进程,因此就不会成为低内存时的待回收进程。(但是理论上,在内存极度匮乏的情况下,这个进程仍有可能被回收。实际上,一般不会有这么极端的情况)。

注意,这说明当我们的Service正在运行的时候,它都不会被系统杀死,除非内存快满了。如果Service被杀掉了,那么随后系统还会尝试着重新启动Service。这样子,我们就必须考虑到如果我们实现onStartCommand()方法,用异步或者其他线程来完成Service的任务,那么我们就可能需要使用START_FLAG_REDELIVERY 让系统重新传递一个Intent,以便在Service重新启动后,Intend会丢失。

在同一个进程中的应用程序组件(application components)像Service(或者Activity)可以增加进程在所有进程中的重要性,而不是仅仅增加Service的重要性。

补充说明:

前面谈到Service是由系统进行调度的,那么对我们来讲有什么意义呢?他又体现在什么地方呢?

因为Service是由系统进行调度的,那么它的生命周期与Activity的生命周期也就无关了,也就是假设ServiceA是由ActivityA启动的,即使当ActivityA因为某种原因调用了OnDestroy()方法将自己销毁掉之后,ServiceA依然欢快地运行着。

Android中Service深入学习的更多相关文章

  1. Android中Service(服务)详解

    http://blog.csdn.net/ryantang03/article/details/7770939 Android中Service(服务)详解 标签: serviceandroidappl ...

  2. Android中Service的使用详解和注意点(LocalService)

    Android中Service的使用详解和注意点(LocalService) 原文地址 开始,先稍稍讲一点android中Service的概念和用途吧~ Service分为本地服务(LocalServ ...

  3. Android中Service的一个Demo例子

    Android中Service的一个Demo例子  Service组件是Android系统重要的一部分,网上看了代码,很简单,但要想熟练使用还是需要Coding.  本文,主要贴代码,不对Servic ...

  4. Android中Service和Activity之间的通信

    启动Service并传递数据进去: Android中通过Intent来启动服务会传递一个Intent过去. 可以在Intent中通过putExtra()携带数据 Intent startIntent ...

  5. Android中Service 使用详解(LocalService + RemoteService)

    Service 简介: Service分为本地服务(LocalService)和远程服务(RemoteService): 1.本地服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外L ...

  6. Android中Service的使用

    我个人的理解是:我们平时使用的android系统的app的后台应用,就是这个原理 可以利用Service实现程序在后台运行,依照这个原理,可以通过Service来实现关键代码的运行与实现. <一 ...

  7. (六)Android中Service通信

    一.启动Service并传递参数 传递参数时只需在startService启动的Intent中传入数据便可,接收参数时可在onStartCommand函数中通过读取第一个参数Intent的内容来实现 ...

  8. android中service启动后台程序

    Service是Android中一个类,它是Android四大组件之一,使用Service可以在后台执行长时间的操作( perform long-running operations in the b ...

  9. Android中Service与多个Activity通信

    由于项目需要,我们有时候需要在service中处理耗时操作,然后将结果发送给activity以更新状态.通常情况下,我们只需要在一个service与一个activity之间通信,通常这种情况下,我们使 ...

随机推荐

  1. mongo 查找附近点

    db.runCommand({geoNear:"demo", near: { type: "Point" , coordinates: [118.134535, ...

  2. Substance 6 设置 watermark(水印)

    http://www.qumake.com/articles/2011/04/18/1303094833690.html ——————————————————————————————————————— ...

  3. 8.12 CSS知识点5

    背景原点 background-origin 设置元素背景图片的原始起始位置,必须保证背景是background-repeat为no-repeat此属性才会生效. 语法: background-ori ...

  4. 64 位 Ubuntu 下 android adb 不可用解决方法

    解决方案: 安装ia32-libs 在终端执行 sudo apt-get install ia32-libs 其间会提示所依赖的某些包不存在,直接 sudo apt-get 安装即可.

  5. 红星美凯龙CEO车建新的圆融和霸气

    待人接物中车建新有许多习惯,与别人一起行走时,走在靠马路的一边:吃饭时最好的菜留给客人.他说,做人往往就在细节中,别小看一个举动,无意中就会感染别人.和别人在一起,你要时时刻刻先考虑对方. 细节上体察 ...

  6. 基于CCS3.3平台搭建DSP/BIOS系统

    本人由于换工作的原因,由ccs3.1平台下转化为ccs3.3平台.先说说本人感觉的区别,ccs3.1下的CSL库集成到DSP/BIOS内,而3.3的CSL库在DSP/BIOS下就没有体现. 1.二话不 ...

  7. args

    java 中args一般存在main主类方法内,String args[ ]或者String[ ] args表示给主方法传一个字符串数组. 而args是一个字符串数组的变量名,不是关键字,是argum ...

  8. [其他] 蒙特卡洛(Monte Carlo)模拟手把手教基于EXCEL与Crystal Ball的蒙特卡洛成本模拟过程实例:

    http://www.cqt8.com/soft/html/723.html下载,官网下载 (转帖)1.定义: 蒙特卡洛(Monte Carlo)模拟是一种通过设定随机过程,反复生成时间序列,计算参数 ...

  9. .net 更新数据 ado.net parameter

    UPDATE yborder_ordernotes SET recoder400= @FileAddress, havefile400 = 1 WHERE id = @OrderID Maticsof ...

  10. 请不要做浮躁的IT人

    1.不要看到别人的回复第一句话就说:给个代码吧!你应该想想为什么.当你自己想出来再参考别人的提示,你就知道自己和别人思路的差异. 2.初学者请不要看太多太多的书那会误人子弟的,先找本系统的学,很多人用 ...