Service

零、资料

一、简介

Android 四大组件中的计算型组件,无用户界面、在后台运行、生命周期长。
常用作提供在后台长期运行的服务,如复杂计算、音乐播放、下载等。

二、生命周期

1.生命周期图

Service 生命周期

2.外部调用方法

当在活动中调用服务时可调用如下方法。

startService()

  • 启动服务
  • 调用:onCreate()onStartCommand()
  • 流程:
    startService() 流程

stopService()

  • 关闭服务

  • 调用:onDestory()

  • 流程:
    stopService() 流程
  • 说明:当服务为绑定状态需先解除绑定后再调用stopService()关闭服务,直接调用stopService()无法停止服务。

bindService()

  • 绑定服务
  • 调用:onCreate()onBind()
  • 流程:
    bindService() 流程
  • 说明:boolean bindService(Intent service, ServiceConnection conn, int flags)
    • Intent:意图
    • ServiceConnection:监听服务状态
      • onServiceConnected活动与服务成功绑定
        • onServiceConnected(ComponentName name, IBinder service) IBinder为服务的Binder实例,可通过此实例来进行服务的操作。调用指定服务执行响应操作。
      • onServiceDisconnected活动与服务解绑
    • 标志位:
      • 官方说明
      • BIND_AUTO_CREATE:只要绑定存在,就自动创建服务。
      • ...

unbindService()

  • 解绑服务
  • 调用:onUnbind()onDestory()
  • 流程:
    unbindService() 流程

3.Service方法

onCreate()

  • 创建服务
  • 服务创建时调用,创建后不会再调用。

onStartCommand()

  • 开始服务
  • 说明:返回值描述了系统在杀死服务后应该如何继续运行。
    • 官方说明
    • START_NOT_STICKY:不重建服务(还存在未发送的intent除外)
    • START_STICKY:重建服务&调用onStartCommand()但用null intent来调用onStatCommand()(还存在未发送的intent除外) 。适用于媒体播放器类似服务,它们不执行命令,但需要一直运行并随时待命)
    • START_REDELIVER_INTENT:重建服务&用上一个已送过的intent调用onStartCommand()。适用于那些需要立即恢复工作的活跃服务,比如下载文件。
    • ...

onDestroy()

  • 销毁服务
  • 服务器销毁时调用。

onBind()

  • 绑定服务
  • IBinder onBind(Intent intent)
  • 用来活动与服务进行通信。

onUnbind()

  • 解绑服务

stopSelf()

  • 停止服务

三、其他常用方法

1.startForeground

  • startForeground(int id, Notification notification) 使后台服务变为前台服务
    • id:通知id
    • notification:通知对象

2.stopForeground

  • 从前台状态中删除此服务,此时服务并未停止。

3.配置

android:enabled=["true" | "false"]

  • 是否这个服务能被系统实例化,如果能则为true,否则为false。默认为true。

android:exported=["true" | "false"]

  • 是否其它应用组件能调用这个服务或交互,能为true,默认值依赖于是否包含过滤器。

android:process=["Sting"]

  • 是否需要在单独的进程中运行,值为进程名称,默认主进程。

四、编写形式

1.较标准的服务

  • 服务中的代码默认运行在主线程当中,如果直接在服务里去处理一些耗时的逻辑,就很容易出现ANR ( Application Not Responding)的情况。

  • 我们应该在服务的每个具体的方法里开启一个子线程,然后在这里去处理那些耗时的逻辑。

  • 因此,一个比较标准的服务就可写成如下形式:

    public class MyService extends Service {
      ...
      
      @override
      public int onStartCommand(Intent intent, int flags, int startId) {
        new Thread(() -> {
          // TODO 处理具体的逻辑
          
          // 执行完立即关闭碰
          // stopSelf(); 
        }).start();
        return super.onStartCommand(intent, flags, startId);
      }
    }
    

五、分类

1.本地 vs 远程

了解IPCAIDL能更理解本地服务远程服务

  • IPC:Inter-Process Communication,即跨进程通信。
  • AIDL:Android Interface Definition Language,即Android接口定义语言。用于让某个Service与多个应用程序组件之间进行跨进程通信,从而可以实现多个应用程序共享同一个Service的功能。

本地服务(LocalService)

  • 运行在主线程(节约资源)。
  • 主线程被终止后,服务也会终止(限制性大)。
  • 由于在同1进程因此不需IPCAIDL通信。
  • 最常用的服务类型,如音乐播放。

远程服务(RemoteService)

  • 运行在独立进程(消耗资源)。
  • 服务常驻在后台,不受其他Ativity影响(灵活)。
  • 使用AIDL进行IPC通信复杂。
  • 常作为系统级服务。

2.前台 vs 后台

前台服务

  • 通知栏显示通知(用户可见)。
  • 服务使用时,需让用户知道 & 进行相关操作,如音乐播放服务。(服务被终止时,通知栏的通知也会消失)。

后台服务

  • 处于后台(用户无法看到)。
  • 服务使用时不需要让用户知道 & 进行相关操作,如天气更新、日期同步
  • 后台服务(服务被终止时,用户无法知道)。

3.不可通信 vs 可通信

不可通信的后台服务

  • startService()启动,调用者退出后服务仍然存在。
  • 服务不需与Activity&Service通信。

可通信的后台服务

bindService() 启动:

  • bindService()绑定,调用者退出后服务销毁。
  • 服务需与Activity&Service通信、需控制服务开始时刻。
  • 节约系统资源,第一次BindService()时才会创建服务的实例 & 运行,当服务为远程服务(Remote Service)时效果明显。
  • 服务只是公开一个远程接口,供客户端Android/iOS远程调用执行方法。
  • BroadcastReceiver也可完成需求,但若交互频綮,容易造成性能问题。且BroadcastReceiver本身执行代码的时间非常短且可能执行到一半,后面的代码便不会执行。而服务则没有这些问题。

StartService()、bindService()启动:

  • StartService()bindService()启动,调用者退出后服务销毁。
  • 服务需与Activity&Service通信、不需控制服务开始时刻(服务一开始便运行)。

六、IntentService

作用

处理异步请求 & 实现多线程,任务按顺序、在后台执行,执行后自行关闭。常用做离线下载等。

流程

IntentService 流程

本质

IntentService = Handler + HandlerThread

  1. 通过HandlerThread单独开启1个工作线程:IntentService
  2. 创建1个内部HandlerServiceHandler
  3. 绑定ServiceHandlerIntentService
  4. 通过onStartCommand()传递服务intentServiceHandler、依次插入Intent到工作队列中 & 逐个发送给onHandleIntent()
  5. 通过onHandleIntent()依次处理所有Intent对象所对应的任务。

因此我们通过复写onHandleIntent() & 在里面根据Intent的不同进行不同线程操作即可。

说明

  • 多次启动IntentService,每个耗时操作以队列的方式在IntentServiceonHandleIntent回调方法中依次执行,执行完自动结束。
  • 工作任务队列是顺序执行的,若服务停止,则会清除消息队列中的消息,后续的事件不执行。
  • 不建议通过bindService()启动IntentService。在IntentServiceonBind()默认返回null

项目Demo

Demo地址 中的 Service [module]


2019-11-01

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

推荐阅读更多精彩内容