Android Service 文档
应用场景:
1 用于将后台逻辑(Service中)和UI逻辑(Activity中)进行解耦,实现Service功能的复用,为其他程序提供功能。
2 后台功能,由于Activity在进入后台时(OnStop)不会占用CPU进行运算,而Service在后台会一直占用CPU,用Service可以达到多任务效果。
3 默认情况下,Service运行在主线程(UI线程)中,因此耗时的操作(下载)需要在Service新建线程处理或者使用异步(AsyncTask)的方式进行。
4 桌面widget的功能需要用Service实现。
5 能提高进程优先级,当Android系统由于内存资源不足时会考虑将进程回收,此时若需要保证进程不会被结束,将Service运行在前台模式(foreground),此时该进程的优先级与前台进程一样。
6 IntentService类,对于简单的后台任务可以用IntentService实现。
相关回调函数以及生命周期
7 onCreate与onDestroy,相当于构造函数和析构函数,整个生命周期都只执行一次。不论startService或者bindService调用多少次,进程中的同一个Service只会在第一次时执行onCreate;而onDestroy需要调用stopService(若有startService,多次startService只需要一次stopService)和unbindService(若有bindService,每个bindService都要有相应的unbindService)后才会执行。
8 onBind,调用bindService时,若Service还没有启动,则根据不同的flags参数,会有不同的行为。
1) 0,默认值,不启动Service,而当有其他情况使得Service启动时,会自动绑定该Serivce。
2) BIND_AUTO_CREATE,若此时Service还没有启动,则直接启动Service。
3) BIND_DEBUG_UNBIND,会将bindService的调用栈保留以备调试的时候使用。
4) BIND_IMPORTANT,表明该Service非常重要,并且会将进程优先级设为前台进程级别。
5) BIND_NOT_FOREGROUND,不允许Service所在进程成为前台进程。
6) BIND_WAIVE_PRIORITY,不影响Service所在进程的调度和内存优先级。
- onBind的主要作用是与调用者通过返回值IBinder建立连接,以便进行交互。
9 onUnbind,调用unbindService时执行,其返回值影响onRebind回调的运行情况。只有当返回值为true,onRebind才能运行。
10 onRebind,当Service由于内存不足被系统回收后,内存再次足够时,Service重新启动后就会执行。受onUnbind返回值影响。
11 onStartCommand,每次调用startService都会执行该回调函数。如果有一次性的任务可以放在该函数中执行,这样每次调用startService都会执行该任务。
后台服务最佳实践
12 不要在Service中直接进行耗时操作,这样会阻塞主线程(UI),应该将其放到另外的线程中运行。
13 对于简单可重复的任务,优先推荐使用IntentService。IntentService类中有自己的线程处理任务。通过在传递的Intent中附带数据,使用Broadcast将Service中信息传回客户端[1]进行通信。
14 使用AlarmManager、Thread和Service实现轮询,能只用AlarmManager就尽量不要带Service[2]。
15 保持Service一直运行的方案:
1) 提升优先级,设为foreground运行,
2) 注册系统广播(开机启动、屏幕解锁等),
3) 开启两个Service,相互绑定监听,若对方被强制结束就将其重启(微信、QQ等),
4) 将程序安装到/system/app中,使其成为系统程序,需要root权限。
Service客户端相关
安卓Service组件的客户端就是能进行startService/stopService和bindService/unbindService操作的组件,一般情况下Activity、Broadcast receiver和Service都可以成为Service组件的客户端。
Activity是最常用的Service客户。对于Activity可以在其onCreate()/onDestroy(), onStart()/onStop(), onPause()/onResume()中实现启动和绑定Service/停止和解绑定操作(如果需要Service在后台运行,那么就不需要停止操作),因为这三组Activity回调在其生命周期中都是一一对应的,也就对应了Service资源的分配和回收情况。其中onCreate()/onDestroy()对应了服务需要在整个app的生命周期中都持续进行的情况,比如IM软件需要在后台持续进行网络通信服务,如果在其他两组回调中实现,那么一旦app进入后台,网络连接就会断掉(一般IM软件不会在onDestroy中停止Service,而是保持Service运行以保证不会错过消息);onStart()/onStop()对应的是该Activity在前台时需要的服务,比如更新Activity的UI界面时,这种情况下一旦onStop就结束Service并进行资源回收(主要防止serviceConnectionLeak),当Activity重新可见时,就重新开启并绑定Service。并不推荐在onPause()/onResume()中进行Service绑定和解绑定,因为这两个回调的执行频率非常高,应该要保持这中间的代码尽量只做轻量级的工作。除了在Activity的生命周期回调中绑定和解绑定Service外,还可以由UI事件触发(比如Button的click事件),此时必须要注意是否已经绑定,以及后续解绑定(可以放在onDestroy或onStop中),防止serviceConnectionLeak。
对于Broadcast receiver,其生命周中最主要就是onReceive回调,因此Service常常在此回调中开启。由于receiver的生命周期非常短(不能超过10s,否则就会ANR),因此不能使用bindService,只能startService开启服务。比如安卓的开机自启动就是通过接收BOOT_COMPLETED这个广播实现的,首先继承BroadcastReceiver类并在onReceive中开启Service,最后在AndroidManifest.xml 文件中注册该receiver。
Service和Service相互服务一般就是为了监控对方的运行状态以防止被系统收回。另外Service还可以直接为UI组件进行服务,比如在Service生命周期更新Notification的状态等。
Service绑定交互
Service与客户端绑定后进行交互主要有三种方法:Binder、Messenger和AIDL。
第一种方法适合与Service和客户运行在同一个进程中,比如Service由Activity启动并绑定的。在Service的onBind中返回Binder,客户Activity接收此Binder,并通过调用Binder公有方法甚至Service的方法与Service的交互。除非需要与其他进程的组件进行交互,就应该首选该方案。
第二种方法是使用Messenger,在此方法中Service需要定义一个Handler以处理各种Message。客户端通过该Service返回的Binder中获取到Messenger,通过向该Messenger发送Message,Service中的Handler进行处理,客户端也可以定义自己的Messenger,这样Service可以将Message传回给客户端。通过这种方式可以实现进程间的通信,这也是安卓推荐的IPC方式。
最后一种是使用AIDL(Android Interface Definition Language)。Messenger的底层实际上就是使用AIDL实现的。这种方法需要用aidl文件定义编程接口,然后由Android SDK 工具生成对应的接口类,最后实现这些接口。该方法与Messenger的优势是效率高,Messenger通过Handler进行消息处理,Handler使用消息队列,一次只能处理一个Message,AIDL则没有这种限制。缺点是服务器和客户端都需要aidl文件,它们之间的接口要保持兼容,因此IPC优先推荐使用Messenger。
除了通过Bind到Service进行交互外,还可以使用Application组件在一个程序的各个组件之间进行数据分享。主要思路是将数据保存在Application中,Application实现为一个Observer,其他组件实现为Listener,注册到Application上,这样当数据发生变动时,通知所有的Listener调用相应的回调。
Android Service 文档的更多相关文章
- Android SDK文档如何查找
		肯定很多人都会有疑问,怎样使用Android SDK 文档该如何使用呢?里面有那么多内容,又全是英文的,接下来告诉大家. 以下内容来自网络. ----------------------------- ... 
- 三种方法解决android帮助文档打开慢
		三种方法解决android帮助文档打开慢 经查是因为本地文档中的网页有如下两段js代码会联网加载信息,将其注释掉后就好了 <link rel="stylesheet" h ... 
- 提高打开Android本地文档的速度
		非常多Android开发人员在參考Android官方API时,都有一个令人头疼的问题:打开一个index.html平均都须要几分钟甚至更长.尤其是在打开API 8以上的版本号的时候.难道是网速不够好? ... 
- Android 开发者文档 -- 应用基础知识
		https://developer.android.com/guide/components/fundamentals 应用基础知识 Android 应用采用 Java 编程语言编写.Android ... 
- 关于android帮助文档打开慢
		打开慢的原因是:Doc目录下的html文件里含有访问google的js文件<link rel="stylesheet"href="http://fonts.goog ... 
- Android API 文档 离线秒开方法
		http://blog.csdn.net/haifengzhilian/article/details/39898627 也是最近才看Android开发,但是,它的API文档无论是在线还是离线的,实在 ... 
- Android XML文档解析(一)——SAX解析
		---------------------------------------------------------------------------------------------------- ... 
- 安装的Android SDK下无doc文件夹问题 以及关联Android帮助文档和查看文档 以及查看在线文档
		参考连接:https://blog.csdn.net/fangzicheng/article/details/78344521 https://jingyan.baidu.com/article/29 ... 
- 受不了Android SDK文档打开缓慢问题,自己开发简易脱机浏览器。
		google android sdk离线文档打开的时候特别慢,据说是要从谷歌官网拉取一些东西导致的.脱机浏览能够解决该问题.PC端能够使用firefox. 可是Android端貌似没有支持脱机工作的浏 ... 
随机推荐
- Python学习资料整理以及书籍、开发工具推荐
			我不知道大家学习Python的时候是不是和我一样感觉很无助,不知道在入门或者进阶的时候应该掌握哪些知识点,下面我就梳理下我自己学习Python开 发的过程及资料分享给大家,这些方法资料可能并不适合所有 ... 
- Ubuntu 14.04中Mysql中文乱码问题最小化解决
			[client]default-character-set=utf8 [mysqld]default-storage-engine=INNODBcharacter-set-server=utf8col ... 
- Devexpress datagrid动态添加显示指定列的gridView
			代码如下: public class DXGridControlHelper { /// <summary> /// 获取显示指定列的GridView /// </summary&g ... 
- Unity UGUI RectTransform图解
			UGUI RectTransform.Unity RectTransform详解 The first:look look API. http://docs.unity3d.com/ScriptRefe ... 
- C语言数组初始化
			例如: int a[15] = {0}; 第一种,编译器会把第一个初始化值赋给数组的第一个元素,然后用0赋给其余的元素.如果没有给出初始值,编译器不会去做初始化工作.这样简洁的方式让代码更加高效. 还 ... 
- Kerberos安装及使用
			转载请注明出处:http://www.cnblogs.com/xiaodf/ 2. 安装 Kerberos2.1. 环境配置 安装kerberos前,要确保主机名可以被解析. 主机名 内网IP 角色 ... 
- python数据结构与算法——图的基本实现及迭代器
			本文参考自<复杂性思考>一书的第二章,并给出这一章节里我的习题解答. (这书不到120页纸,要卖50块!!,一开始以为很厚的样子,拿回来一看,尼玛.....代码很少,给点提示,然后让读者自 ... 
- UVA340 猜数字游戏
			一个经典的找数字位置正确并且找到正确数列中存在的数字而错误的序列存在但是不是正确位置的算法. 看似很难的算法,但是lrj却很简单解决. #include<cstdio> #define M ... 
- 解决Ubuntu输入正确密码后无法进入桌面,一直停留在登陆界面的问题
			在登陆界面按下Ctrl + Shift + F1 进入命令行模式,输入你的用户名和密码之后,敲入下面几行命令就可以了! $ cd - $ sudo chown 你的用户名:你的用户名 .Xauthor ... 
- 数据库之mysql存储程序
			什么时候会用到存储过程 1.存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般 SQL 语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度2.当对数据库进行复杂操作时 ... 
