应用场景:

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 文档的更多相关文章

  1. Android SDK文档如何查找

    肯定很多人都会有疑问,怎样使用Android SDK 文档该如何使用呢?里面有那么多内容,又全是英文的,接下来告诉大家. 以下内容来自网络. ----------------------------- ...

  2. 三种方法解决android帮助文档打开慢

    三种方法解决android帮助文档打开慢   经查是因为本地文档中的网页有如下两段js代码会联网加载信息,将其注释掉后就好了 <link rel="stylesheet" h ...

  3. 提高打开Android本地文档的速度

    非常多Android开发人员在參考Android官方API时,都有一个令人头疼的问题:打开一个index.html平均都须要几分钟甚至更长.尤其是在打开API 8以上的版本号的时候.难道是网速不够好? ...

  4. Android 开发者文档 -- 应用基础知识

    https://developer.android.com/guide/components/fundamentals 应用基础知识 Android 应用采用 Java 编程语言编写.Android ...

  5. 关于android帮助文档打开慢

    打开慢的原因是:Doc目录下的html文件里含有访问google的js文件<link rel="stylesheet"href="http://fonts.goog ...

  6. Android API 文档 离线秒开方法

    http://blog.csdn.net/haifengzhilian/article/details/39898627 也是最近才看Android开发,但是,它的API文档无论是在线还是离线的,实在 ...

  7. Android XML文档解析(一)——SAX解析

    ---------------------------------------------------------------------------------------------------- ...

  8. 安装的Android SDK下无doc文件夹问题 以及关联Android帮助文档和查看文档 以及查看在线文档

    参考连接:https://blog.csdn.net/fangzicheng/article/details/78344521 https://jingyan.baidu.com/article/29 ...

  9. 受不了Android SDK文档打开缓慢问题,自己开发简易脱机浏览器。

    google android sdk离线文档打开的时候特别慢,据说是要从谷歌官网拉取一些东西导致的.脱机浏览能够解决该问题.PC端能够使用firefox. 可是Android端貌似没有支持脱机工作的浏 ...

随机推荐

  1. wiglewifi

    以上数据是使用wiglewifi软件收集的数据,把全部数据导出为KML格式,使用Google地球显示的,当然在大陆地区Google地球有些不正常,我使用的是lantern 以前使用lantern总是不 ...

  2. 转载--JAVA读取文件最佳实践

    1.  前言 Java应用中很常见的一个问题,如何读取jar/war包内和所在路径的配置文件,不同的人根据不同的实践总结出了不同的方案,但其他人应用却会因为环境等的差异发现各种问题,本文则从原理上解释 ...

  3. AMQP与RabbitMQ简介

    MQ(Message Queue,消息队列)是一种应用系统之间的通信方法.是通过读写出入队列的消息来通信(RPC则是通过直接调用彼此来通信的). 1.AMQP协议 在了解RabbitMQ之前,首先要了 ...

  4. PyCharm5.0.2最新版破解注册激活码(图文版)

    下载PyCharm http://download-cf.jetbrains.com/python/pycharm-professional-5.0.2.exe 安装PyCharm 设置激活服务器   ...

  5. 台球游戏的核心算法和AI(1)

    前言: 08年的时候, 写过一个台球游戏, 用的是java, 不过代码真的是用传说中的神器notepad写的(你信吗? 其实是用GVIM写的, ^_^), 很多类都在同一java文件中编写. 可见当时 ...

  6. Codeforces Round #158 (Div. 2)

    A. Adding Digits 枚举. B. Ancient Prophesy 字符串处理. C. Balls and Boxes 枚举起始位置\(i\),显然\(a_i \le a_j, 1 \l ...

  7. JavaScript 使用词法作用域,没有动态作用域

    function foo() { console.log( a ); } function bar() { var a = 3; foo(); } var a = 2; bar(); 上面的代码,控制 ...

  8. 【IOI2000】邮局设置问题

    现在连基础DP都要看题解和代码才能写出来了,怎么办嘛QAQ 原题: 一些村庄建在一条笔直的高速公路边上,我们用一条坐标轴来描述这条公路,每个村庄的坐标都是整数,没有两个村庄的坐标相同.两个村庄的距离定 ...

  9. 蓝牙协议栈中的 OSAL

    蓝牙协议栈里的操作系统叫做 OSAL(操作系统抽象层).它并非一个真正意义上的操作系统,它只是实现了操作系统的一些功能,如任务切换.内存管理. OSAL 产生的根源:基于蓝牙协议栈开发的产品,实际上是 ...

  10. ASP.NET中数据邦定效率问题的一点看法 - 转载(自由的天空)

    在 做Asp.NET开发的时候经常用到DataList.Repeater等,用这些控件的时候经常用到数据邦定,很多程序员都是按照MS提供的方 法<%#DataBinder.Eval(Contai ...