Service

作者: Demon鑫 | 来源:发表于2019-11-01 11:00 被阅读0次

零、资料

一、简介

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

相关文章

网友评论

      本文标题:Service

      本文链接:https://www.haomeiwen.com/subject/tobtbctx.html