Android Service基础知识

Service 作为android 四大组件之一,主要用于再后台处理一些耗时的逻辑或者去执行一些长期运行的任务。

一、startService 和 bindService

1. 生命周期和启动方式:

service_lifecycle.png

1.1 启动
通过startService启动服务时,如果是第一次启动,会调用onCreate->onStartCommand,但是多次启动时不会再调用onCreate,只有onStartCommand会被调用多次。
通过bindService绑定服务时,如果服务还未启动,会调用onCreate->onBind,创建并且绑定服务,多次调用bindService并不会多次调用onBind(),除非是多个客户端来绑定服务。

1.2 销毁
如果组件通过调用 startService() 启动服务,则服务将一直运行,直到服务使用 stopSelf()自行停止运行,或由其他组件通过调用 stopService() 停止它为止。无论服务被启动了多少次,只要调用一次stopService,便可终止(不考虑被绑定过的情况)。

如果组件是通过调用 bindService()来创建服务(且未调用onStartCommand()),则服务只会在该组件与其绑定时运行。一旦该服务与所有客户端之间的绑定全部取消,系统便会销毁它。

2. starService和bindService一起使用:

如果一个Service又被启动又被绑定,则该Service会一直在后台运行。首先不管如何调用,onCreate始终只会调用一次。startService调用多少次,Service的onStartCommand方法便会调用多少次。Service的终止,需要unbindService和stopService同时调用才行。不管startService与bindService的调用顺序,如果先调用unbindService,此时服务不会自动终止,再调用stopService之后,服务才会终止;如果先调用stopService,此时服务也不会终止,再次调用unbindService或者之前调用bindService的Context不存在了 ,服务才会停止。

3. 使用场景:

startService 主要用于开启服务,例如后台下载和播放音乐
bindService 主要为了使用服务中的一些功能或者与服务进行交互
这2种模式不是完全分离的。你可以可以绑定到一个通过startService()启动的服务。如一个intent想要播放音乐,通过startService启动后台播放音乐的service。然后,也许用户想要操作播放器或者获取当前正在播放的乐曲的信息,一个activity就会通过bindService建立一个到此service的连接. 这种情况下 stopService() 在全部的连接关闭后才会真正停止service。

Tips:

  1. 服务的onCreate和onDestroy在一个生命周期中只会执行一次
  2. service的stopself方法的功能是,当完成所有功能之后,将service停掉
  3. Service中onRebind方法被调用的时机,需要满足2个条件:
    (1)服务中onUnBind方法返回值为true
    (2)服务对象被解绑后没有被销毁,之后再次被绑定

2. onStartCommand的返回值:

请注意,onStartCommand() 方法必须返回整型数。整型数是一个值,用于描述系统应该如何在服务终止的情况下继续运行服务(如上所述,IntentService 的默认实现将为您处理这种情况,不过您可以对其进行修改)。从onStartCommand()返回的值必须是以下常量之一:

1. START_NOT_STICKY

如果系统在 onStartCommand() 返回后终止服务,则除非有挂起 Intent 要传递,否则系统不会重建服务。这是最安全的选项,可以避免在不必要时以及应用能够轻松重启所有未完成的作业时运行服务。

2. START_STICKY

如果系统在 onStartCommand() 返回后终止服务,则会重建服务并调用 onStartCommand(),但不会重新传递最后一个 Intent。相反,除非有挂起 Intent 要启动服务(在这种情况下,将传递这些 Intent ),否则系统会通过空 Intent 调用 onStartCommand()。这适用于不执行命令、但无限期运行并等待作业的媒体播放器(或类似服务)。

3. START_REDELIVER_INTENT

如果系统在 onStartCommand() 返回后终止服务,则会重建服务,并通过传递给服务的最后一个 Intent 调用 onStartCommand()。任何挂起 Intent 均依次传递。这适用于主动执行应该立即恢复的作业(例如下载文件)的服务。

二、前台服务

Service几乎都是在后台运行的,一直以来它都是默默地做着辛苦的工作。但是Service的系统优先级还是比较低的,当系统出现内存不足情况时,就有可能会回收掉正在后台运行的Service。如果你希望Service可以一直保持运行状态,而不会由于系统内存不足的原因导致被回收,就可以考虑使用前台Service。前台Service和普通Service最大的区别就在于,它会一直有一个正在运行的图标在系统的状态栏显示,下拉状态栏后可以看到更加详细的信息,非常类似于通知的效果。当然有时候你也可能不仅仅是为了防止Service被回收才使用前台Service,有些项目由于特殊的需求会要求必须使用前台Service,比如说墨迹天气。

    Intent intent = new Intent(this, MainActivity.class);
    //需要让Activity运行在新的任务栈中
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    Notification.Builder builder = new Notification.Builder(this);
    Notification notification = builder.setSmallIcon(R.mipmap.ic_launcher)
            .setContentText("this is a notify")
            .setContentTitle("notify!!!").setTicker("notify")
            .setContentIntent(PendingIntent.
                    getActivity(ServiceB.this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT))
            .build();
    startForeground(1, notification);

Tips:

  1. startForeground让服务变成前台服务并显示通知,这时必须要setSmallIcon,否则会显示默认的通知,不显示自定义通知
  2. 如何让服务一直存活 http://zhoujianghua.com/2015/07/28/black_technology_in_alipay/

三、Service 和 Thread

之所以有不少人会把它们联系起来,主要就是因为Service的后台概念。Thread我们大家都知道,是用于开启一个子线程,在这里去执行一些耗时操作就不会阻塞主线程的运行。而Service我们最初理解的时候,总会觉得它是用来处理一些后台任务的,一些比较耗时的操作也可以放在这里运行,这就会让人产生混淆了。但其实Service其实是运行在主线程里的,所以说service的主进程中不能执行耗时的任务,需要另外启动线程执行,例如IntentService的内部就是使用了HandlerThread的实现。

四、IntentService

IntentService是Service 的子类,它使用工作线程逐一处理所有启动请求。如果不要求服务同时处理多个请求,这是最好的选择。只需实现 onHandleIntent() 方法即可,该方法会接收每个启动请求的Intent,能够执行后台工作。由于大多数启动服务都不必同时处理多个请求,因此使用 IntentService 类实现服务也许是最好的选择。

IntentService的特点:

  1. IntentService 会创建一个线程,来处理所有传给onStartCommand()的Intent请求
  2. 创建一个请求队列,用于将 Intent 逐一传递给 onHandleIntent() 实现,不必担心多线程问题
  3. 在所有的请求执行完毕后结束Service
  4. 提供 onBind() 的默认实现(返回 null)
  5. 提供默认的 onStartCommand() 实现,将intent传入等待队列中,然后到onHandleIntent()的实现。所以如果需要重写onStartCommand() 方法一定要调用父类的实现。

Tips:

  1. IntentService是针对StarteService设计的,由于它默认实现的onBind()方法返回值是null,所以不适合bindService()
  2. 多次startService请求执行耗时任务,不会并发执行onHandleIntent()方法,而是一个一个顺序执行。当所有的任务执行完成,IntentService会自动销毁

问题:onStartCommand的返回值的具体应用场景?

Demo:
http://download.csdn.net/detail/time_traveller14/9886836

参考资料:
https://developer.android.com/guide/components/services.html
http://blog.csdn.net/guolin_blog/article/details/11952435

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容

  • 前言:本文所写的是博主的个人见解,如有错误或者不恰当之处,欢迎私信博主,加以改正!原文链接,demo链接 Serv...
    PassersHowe阅读 1,402评论 0 5
  • 服务基本上分为两种形式 启动 当应用组件(如 Activity)通过调用 startService() 启动服务时...
    pifoo阅读 1,254评论 0 8
  • [文章内容来自Developers] Service是一个可以在后台执行长时间运行操作而不提供用户界面的应用组件。...
    岳小川阅读 857评论 0 7
  • 转载注明出处:http://www.jianshu.com/p/a1d3d9693e91 1. 简介 与前一篇An...
    王三的猫阿德阅读 1,902评论 1 9
  • 描述 给出一棵二叉树,返回其节点值从底向上的层次序遍历(按从叶节点所在层到根节点所在的层遍历,然后逐层从左往右遍历...
    6默默Welsh阅读 505评论 0 1