Android之Service总结篇

1.Service的基本认识

1.1 Service是什么?

Service(服务)是一个一种可以在后台执行长时间运行操作而没有用户界面的组件。它运行于UI线程,因此不能进行耗时的操作。

1.2 Service和Thread的区别

Service的运行是在UI线程当中的,是绝对绝对不能进行 耗时操作 的,而Thread开启的子线程则可以进行耗时操作;
但是Thread开启的子线程是不能直接 对UI进行操作 的,否则极有可能发生直接让程序崩掉,这就是它们的区别。

1.3 能否在Service开启耗时操作 ? 怎么做 ?

service 默认并不会运行在子线程中,也不运行在一个独立的进程中,它同样 执行在主线程中(UI线程)。

换句话说,不要在 Service 里执行耗时操作,除非手动打开一个子线程,否则有可能出现主线程被阻塞(ANR)的情况;

1.4 常见服务

在这里插入图片描述

2.启动Service的2种方式

2.1 startService()方法开启Service

步骤:
a.定义一个类继承Service。
b.在AndroidManifest.xml文件中配置该Service。
c.使用Context的startService(Intent)方法启动该Service。
d.不再使用该Service时,调用Context的stopService(Intent)方法停止该Service

2.2 bindService方法开启Service(Activity与Service绑定)

步骤:
a.创建BinderService服务端,继承自Service并在类中创建一个实现IBinder接口的实现实例对象并提供公共方法给客户端调用。
b.onBind()回调方法返回此Binder实例。
c.在客户端中,从onServiceConnected回调方法接收Binder,并使用提供的方法调用绑定服务。

2.3 两种启动方式的区别

  1. startService():通过这种方式调用 startService,onCreate() 只会被调用一次,多次调用 startSercie 会多次执行 onStartCommand() 和 onStart() 方法。如果外部没有调用 stopService() 或 stopSelf() 方法, service 会一直运行。

  2. bindService():如果该服务之前还没创建,系统回调顺序为 onCreate()→onBind()。如果调用 bindService() 方法前服务已经被绑定,多次调用 bindService() 方法不会多次创建服务及绑定。如果调用者希望与正在绑定的服务解除绑定,可以调用 unbindService() 方法,回调顺序为 onUnbind()→onDestroy();

    在这里插入图片描述


3.Service的生命周期

Service的生命周期涉及到六大方法

onCreate():如果 service 没被创建过,调用 startService() 后会执行 onCreate() 回调;如果 service 已处于运行中,调用 startService() 不会执行 onCreate() 方法。
	onCreate()只会在第一次创建service时候调用,多次执行startService()不会重复调用onCreate(),此方法适合完成一些初始化工作;

onStartComand():服务启动时调用,此方法适合完成一些数据加载工作,比如会在此处创建一个线程用于下载数据或播放音乐;

onBind():服务被绑定时调用;

onUnBind():服务被解绑时调用;

onDestroy():服务停止时调用;

服务的生命周期有两种,因为服务可以跟Activity绑定起来,也可以不绑定,Activity和服务进行通信的话,是需要把服务和Activity进行绑定的。因此服务的生命周期分为未绑定Activity的和绑定Activity的。

3.1 没有绑定Activity的服务生命周期图

在这里插入图片描述

  1. 通过 Intent 和 startService() 方法启动了一个服务,接下来执行onCreate() 方法,首次创建服务时,系统将调用此方法来执行一次性设置程序(在调用 onStartCommand() 或 onBind() 之前)。如果服务已在运行,则不会调用此方法。

  2. 当另一个组件(如 Activity)通过调用 startService() 请求启动服务时,系统将调用此方法。一旦执行此方法 onStartConmmand(),服务即会启动并可在后台无限期运行。 如果实现了此方法,则在服务工作完成后,需要通过调用 stopSelf() 或 stopService() 来停止服务。(如果只想提供绑定,则无需实现此方法。)

  3. 服务开始处于运行状态。

  4. 某个操作导致服务停止,比如执行了方法 stopService(),那么服务接下来会执行 onDestory() 销毁。服务应该实现此方法来清理所有资源,如线程、注册的侦听器、接收器等。 这是服务接收的最后一个调用。

  5. 服务被完全销毁,下一步就是等待被垃圾回收器回收了。


3.2 绑定Activity的服务生命周期图

在这里插入图片描述

  1. 通过 Intent 和 bindService() 方法启动了一个服务,接下来会执行 onCreate() 方法,首次创建服务时,系统将调用此方法来执行一次性设置程序(在调用 onStartCommand() 或 onBind() 之前)。如果服务已在运行,则不会调用此方法。
  2. 当另一个组件想通过调用 bindService() 与服务绑定(例如执行 RPC)时,系统将调用此方法。在此方法的实现中,您必须通过返回 IBinder 提供一个接口,供客户端用来与服务进行通信。请务必实现此方法,但如果您并不希望允许绑定,则应返回 null。
  3. 服务开始处于运行状态。成功与Activity绑定。
  4. 某个操作导致服务解除绑定,比如执行了方法unbindService(),那么服务接下来会解除与当前Activity的绑定。接下来服务将面临销毁。
  5. 服务执行onDestory()方法被销毁。服务应该实现此方法来清理所有资源,如线程、注册的侦听器、接收器等。 这是服务接收的最后一个调用。
  6. 服务被完全销毁,下一步就是等待被垃圾回收器回收了。

4. 关于服务,总结一下:

  1. 被启动的服务的生命周期:如果一个Service被某个Activity 调用 Context.startService 方法启动,那么不管是否有Activity使用bindService绑定或unbindService解除绑定到该Service,该Service都在后台运行。如果一个Service被startService 方法多次启动,那么onCreate方法只会调用一次,onStart将会被调用多次(对应调用startService的次数),并且系统只会创建Service的一个实例(因此你应该知道只需要一次stopService调用)。该Service将会一直在后台运行,而不管对应程序的Activity是否在运行,直到被调用stopService,或自身的stopSelf方法。当然如果系统资源不足,android系统也可能结束服务。
  2. 被绑定的服务的生命周期:如果一个Service被某个Activity 调用 Context.bindService 方法绑定启动,不管调用 bindService 调用几次,onCreate方法都只会调用一次,同时onStart方法始终不会被调用。当连接建立之后,Service将会一直运行,除非调用Context.unbindService 断开连接或者之前调用bindService 的 Context 不存在了(如Activity被finish的时候),系统将会自动停止Service,对应onDestroy将被调用。
  3. 被启动又被绑定的服务的生命周期:如果一个Service又被启动又被绑定,则该Service将会一直在后台运行。并且不管如何调用,onCreate始终只会调用一次,对应startService调用多少次,Service的onStart便会调用多少次。调用unbindService将不会停止Service,而必须调用 stopService 或 Service的 stopSelf 来停止服务。
  4. 当服务被停止时清除服务:当一个Service被终止(1、调用stopService;2、调用stopSelf;3、不再有绑定的连接(没有被启动))时,onDestroy方法将会被调用,在这里你应当做一些清除工作,如停止在Service中创建并运行的线程。

特别注意
5. 在调用 bindService 绑定到Service的时候,就应当保证在某处调用 unbindService 解除绑定(尽管 Activity 被 finish 的时候绑定会自动解除,并且Service会自动停止);
6. 使用 startService 启动服务之后,一定要使用 stopService 停止服务,不管你是否使用bindService;
7. 同时使用 startService 与 bindService 要注意到,Service 的终止,需要 unbindService 与 stopService 同时调用,才能终止 Service,不管 startService 与 bindService 的调用顺序,如果先调用 unbindService 此时服务不会自动终止,再调用 stopService 之后服务才会停止,如果先调用 stopService 此时服务也不会终止,而再调用 unbindService 或者 之前调用 bindService 的 Context 不存在了(如Activity 被 finish 的时候)之后服务才会自动停止;
8. 当在 旋转手机屏幕的时候,当手机屏幕在“横”“竖”变换时,此时如果你的 Activity 如果会自动旋转的话,旋转其实是 Activity 的重新创建,因此旋转之前的使用 bindService 建立的连接便会断开(Context 不存在了),对应服务的生命周期与上述相同。
9. 在 sdk 2.0 及其以后的版本中,对应的 onStart 已经被否决变为了 onStartCommand,不过之前的 onStart 任然有效。这意味着,如果你开发的应用程序用的 sdk 为 2.0 及其以后的版本,那么你应当使用 onStartCommand 而不是 onStart。


5. 如何保证Service不被杀死 ?

  1. onStartCommand 方式中,返回 START_STICKY 或 START_REDELIVER_INTENT

    1. START_STICKY:如果返回 START_STICKY,表示 Service 运行的进程被 Android 系统强制杀掉之后,Android 系统会将该 Service 依然设置为 started 状态(即运行状态),但是不再保存 onStartCommand 方法传入的 intent 对象
    2. START_NOT_STICKY:如果返回 START_NOT_STICKY,表示当 Service 运行的进程被 Android 系统强制杀掉之后,不会重新创建该 Service
    3. START_REDELIVER_INTENT:如果返回START_REDELIVER_INTENT,其返回情况与 START_STICKY 类似,但不同的是 系统会保留最后一次传入 onStartCommand 方法中的 Intent 再次保留下来并再次传入到重新创建后的 Service 的 onStartCommand 方法中;
  2. 提高 Service 的优先级 在 AndroidManifest.xml 文件中对于 intent-filter 可以通过 android:priority = “1000” 这个属性设置最高优先级,1000 是最高值,如果数字越小则优先级越低,同时适用于广播;

  3. 在 onDestroy 方法里重启 Service ;当 service 走到 onDestroy() 时,发送一个自定义广播,当收到广播时,重新启动 service;

  4. 提升 Service 进程的优先级 进程优先级由高到低:前台进程 一 可视进程 一 服务进程 一 后台进程 一 空进程 可以使用 startForeground 将 service 放到前台状态,这样低内存时,被杀死的概率会低一些;

  5. 系统广播监听 Service 状态

  6. 将APK安装到 /system/app,变身为系统级应用

注意:以上机制都不能百分百保证Service不被杀死,除非做到系统白名单,与系统同生共死


6. AMS 是什么?发挥什么作用

  1. ActivityManagerService 是 Android 中最核心的服务,
  2. 主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作,其职责与操作系统中的进程管理和调度模块类似;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liusaisaiV1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值