Android中Service深入学习
概述
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深入学习的更多相关文章
- Android中Service(服务)详解
http://blog.csdn.net/ryantang03/article/details/7770939 Android中Service(服务)详解 标签: serviceandroidappl ...
- Android中Service的使用详解和注意点(LocalService)
Android中Service的使用详解和注意点(LocalService) 原文地址 开始,先稍稍讲一点android中Service的概念和用途吧~ Service分为本地服务(LocalServ ...
- Android中Service的一个Demo例子
Android中Service的一个Demo例子 Service组件是Android系统重要的一部分,网上看了代码,很简单,但要想熟练使用还是需要Coding. 本文,主要贴代码,不对Servic ...
- Android中Service和Activity之间的通信
启动Service并传递数据进去: Android中通过Intent来启动服务会传递一个Intent过去. 可以在Intent中通过putExtra()携带数据 Intent startIntent ...
- Android中Service 使用详解(LocalService + RemoteService)
Service 简介: Service分为本地服务(LocalService)和远程服务(RemoteService): 1.本地服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外L ...
- Android中Service的使用
我个人的理解是:我们平时使用的android系统的app的后台应用,就是这个原理 可以利用Service实现程序在后台运行,依照这个原理,可以通过Service来实现关键代码的运行与实现. <一 ...
- (六)Android中Service通信
一.启动Service并传递参数 传递参数时只需在startService启动的Intent中传入数据便可,接收参数时可在onStartCommand函数中通过读取第一个参数Intent的内容来实现 ...
- android中service启动后台程序
Service是Android中一个类,它是Android四大组件之一,使用Service可以在后台执行长时间的操作( perform long-running operations in the b ...
- Android中Service与多个Activity通信
由于项目需要,我们有时候需要在service中处理耗时操作,然后将结果发送给activity以更新状态.通常情况下,我们只需要在一个service与一个activity之间通信,通常这种情况下,我们使 ...
随机推荐
- Java串口通信详解
http://blog.csdn.net/kabini/article/details/1601324 ———————————————————————————————————————————————— ...
- android 学习(1)
第二次发生这种事了,写完啦,手一抖,丢了,这个写完不用博客园了,怪不得用户越来越少 简写 androidstudio安装注意点 1JDK安装需配置环境变量 2安装遇到haxm错误需要进入BIOS打开C ...
- WPS项目编号问题
问题:文档需要编号如下: 1.(标题1) 1.1(标题2) 1.1.1(标题3) 1.2 1.2.1 2.(标题1) 2.1(标题2) 2.1.1(标题3) 2.2 2.2.1 方法一: 第一步,打开 ...
- codevs4919 线段树练习4
4919 线段树练习4 时间限制: 1 s 空间限制: 128000 KB 题目描述 Description 给你N个数,有两种操作 1:给区间[a,b]内的所有数都增加X 2:询问区 ...
- 星号代替数字 js语句
在做登陆界面时,有这样一个需求,就是输入密码时,以密文形式展示(*),由于html5的属性 type="password" 只能以圆点形式展示, 下面方法能以星号代替输入符合 d ...
- urllib.request
[urllib.request] 1.urlopen结果保存在内存. 2.ulrretrieve结果保存到文件. 3.response有read方法. 4.可以创建Request对象. 5.发送Pos ...
- androidannotations 简单配置
1.build.gradle 需要添加的内容 标注的颜色是新建项目之后,build.gradle文件需要添加的内容. buildscript { repositories { jcenter() } ...
- Swift3.0基础语法学习<二>
对象和类: // // ViewController2.swift // SwiftBasicDemo // // Created by 思 彭 on 16/11/15. // Copyright © ...
- nodejs--偏函数
偏函数的例子,解释--假设有一个参数或变量已经预置的函数A,我们通过调用A来产生一个新的函数B,函数B就是我们说的偏函数 偏函数解决这样的问题:如果我们有函数是多个参数的,我们希望能固定其中某几个参数 ...
- TFS2010安装办法及序列号
安装过程: 一.安装操纵体系 安装Windows 2008 R2简体中文版 二.筹办安装过程中的须要的用户账户,并设置响应权限 具体流程如下: 1.点击“开端”——“经管对象”——“计较机经管” 2. ...