Android开发笔记(五)- Service组件

Android开发笔记(五)- Service组件

Android开发笔记之基础篇(二)中,我们简单总结了Activity组件的特性和使用方法。在其之后的第二个重要组件就是Service(服务)。简单来说,如果说Activity是负责处理与用户交互的UI部分的内容,那么Service则是负责在后台处理一些长时间,大型的操作或计算的内容。今天我们就继续来看看Service组件的特性以及使用方法。

Service

首先,在Google doc官方说明文档中对Service的解释是:

A Service is an application component that can perform long-running operations in the background. It does not provide a user interface.

所以从这里我们可以很清晰的看到Service的两个特性:后台运行长时间运行。适合使用Service的场景实例有很多,比如播放音乐或者进行网络文件下载,与ContentProvider进行交互等等。在某些情况下,即使App被关闭后,其开启的Service依旧能够在后台运行

Service分类

按照不同的分类方式,Service可以从运行地点,运行类型以及功能进行分类:

运行地点

  • 本地服务(local service):运行在主线程(main thread),受线程的控制,主线程终止时,其也会被终止;
  • 远程服务(remote service):运行在自己的独立线程,常驻后台,不被其他activity影响,但会消耗更多资源

运行类型

  • 前台服务(Forground):所谓“前台”,是指其会在通知栏中显示出来,需要让用户看到,并且终止时通知也会消失
  • 后台服务(Background)不会显示在通知栏,用户无法知晓是否仍在运行。

功能

  • 不可通信:使用startService()直接开启,调用者退出后,该service可继续存在,不可与调用者(例如activity)进行通信
  • 可通信:使用bindService()绑定开启,调用者退出后,该service也会退出并销毁,可以与调用者(例如activity)进行通信

生命周期 Service lifecycle

启动一个Service主要有两种方式:startService() 直接开启bindService()绑定开启,两种方式产生的Service的生命周期不完全相同。先放上Google doc官方文档中给出的说明图:

这里我们首先需要知道,在Service中有四个手动调用的方法:startService(), stopService(), bindService()unbindService(),通过手动调用这四个方法,可以使其自动调用另外五个方法onCreate(), onStartCommand(), onBind(), onDestory()onUnbind()。所以下面我们就对四个需手动调用的方法来一一详细分析其在Service生命周期中的使用方法和规律:

startService()

  • startService()会直接启动Service服务,即使多次手动调用startService() 只会调用一次onCreate(), 但会多次调用onStartCommand()onStartCommand()的调用次数和startService()保持一致,也只有onStartCommand()可以被多次自动调用
  • onStartCommand()被自动调用时,会返回一个整数flag,其用于表示当该Service被系统销毁时要如何处理,这个flag有三种可能的状态:1. START_NOT_STICKY:除非还存在未发送的intent,否则该Service不会被重建;2. START_STICKY: 重建服务,但不会再次发送最近一次已发送的intent,适用于例如媒体播放等需要持续待命,但不用立刻运行的场景;3. START_REDELIVER_STICKY重建服务并发送最近一次已发送的intent,适用于例如文件下载等需要立刻恢复运行的场景;
  • 当返回的flag是START_STICKYSTART_REDELIVER_STICKY时, onStartCommand()也会被重新调用

stopService()

  • stopService()会直接关闭Service服务,但需要注意的是:在已经绑定服务(调用过bindService())之后如果没有解绑,stopService()是不会关闭服务的

bindService()

  • 即使多次手动调用bindService(),实际上onCreate()也只会被调用一次,即只存在一个Service实例;
  • 当一个服务已经通过startService()直接启动之后,依旧可以通过bindService()来绑定服务并使用

unbindService()

  • 如果使用bindService()绑定启动服务,那么
  • 当多个客户端(client)绑定到同一个Service服务时,系统会在所有的客户端都解绑之后自动销毁服务,不需要手动调用unbindService()

题目练习

不妨用以下的test case来测试一下上面的流程图是否已经掌握,通过手动调用方法的顺序来判断Service自动调用方法的顺序:

Service VS IntentService

ServiceIntentService的区别是一个非常常见的面试题目,其主要区别包括:

  • IntentServiceService的一个子类,主要通过一个work queue来处理从客户端接收到的intent,适用于处理较长时间的任务;
  • Service运行在主线程(main thread),无法处理耗时任务,否则主线程阻塞会出现ANR,而IntentService可以在独立的子线程上运行;
  • Service可以从任何线程上启动,而IntentService只能从主线程上启动
  • Service通过手动调用startService()bindService()来开启服务,而IntentService通过Context.startService(Intent)来开启服务;
  • Service通过手动调用stopService()来停止并销毁服务。但IntentService在所有intent被处理完之后自动停止
  • IntentService自动调用onBind()方法并返回一个null值,并为onStartCommand()提供了默认实现,将请求的intent添加进队列中。

参考文章

Google Document: Services overview

JavaTpoint: Android Service Tutorial

Android:Service生命周期 完全解析

Android的Service生命周期

Service vs IntentService in Android

Comments