内容简介:来总结一下 Service 的几个知识要点,包括启动方式、每种启动方式的生命周期、IntentService 源码分析,以及 boundService 三种使用方法。注:API 大于等于 26 时,当 app 不在前台的时候,后台服务会受到限制,这种情况下,官方文档推荐使用 Schedule jobs。startService(): onCreate() -> onStartCommand()/onStart() -> … -> onDestroy()
来总结一下 Service 的几个知识要点,包括启动方式、每种启动方式的生命周期、IntentService 源码分析,以及 boundService 三种使用方法。
Service 三种启动方式
-
前台 Service (startForegroundService(intent)): 在 API 大于等于 26 以上,用来设置通知栏。在调用这个 api 之后应马上调用 Service#startForeground(int, Notification),来设置 Notification,否则系统会自动停止 Service,并发生 ANR。
-
后台 Service (startService(intent)): 如果 app 的一些操作不需要通知用户,则启动后台 Service。
注:API 大于等于 26 时,当 app 不在前台的时候,后台服务会受到限制,这种情况下,官方文档推荐使用 Schedule jobs。
- 绑定 Service (bindService(intent, serviceConnection, flags)): 绑定 Service 提供客户端/服务端模式,组件之间可以用过它发送、接受消息,甚至可以跨进程通信。在调用 unbindService(),Service 就会销毁。
生命周期
startService(): onCreate() -> onStartCommand()/onStart() -> … -> onDestroy()
bindService(): onCreate() -> onBind() -> … -> onUnbind() -> onDestroy()
以上两个生命周期只是对单个 activity start 或者 bind 服务的时候,然而在实际使用的时候,通常会两个结合使用,也或者是多个 activity 对同一个 service 绑定。
- 多个 Activity StartService 时,Service 不会重复启动,onStartCommand() 会重复执行,并获取对应的 intent。当有一个 stopService() 时,Service 会销毁。
- 多个 Activity 绑定和解绑时,Service 会重复走 onBind()/onUnbind()这两个生命周期,但不会销毁,直到没有 Activity 和它有绑定关系的时候,才会销毁。
- 当 StartService/bindService 混合用时,Service 的销毁时机为 stopService。
IntentService 原理
大家都知道,IntentService 的特性是运行在非 UI 线程,可执行耗时操作,当执行完后会自动销毁。我们今天在看一下它的原理:
IntentService 内部由 HandlerThread 维护一个线程,在启动后获取 intent 并发送给 HandlerThread 所在的线程执行,执行完任务后自动调用 stopSelf() 销毁。
具体的源码实现如下:
- 继承 Service;
- onBind(): IntentService 由 startService() 启动,当然不需要 binder,所以这个函数返回 null;
-
onCreate(): 新建 HandlerThread 并启动线程,通过 HandlerThread.getLooper() 新建 Handler。总结起来两句代码,大致如下:
new HandlerThread().start(); new ServiceHandler(thread.getLooper());
-
onStart(): 这个函数中,通过前面新建的 Handler,把 intent 消息发送到非 UI 线程,即:mServiceHandler.sendMessage(msg)。
- ServiceHandler 的 handleMessage 函数实现中,先执行抽象函数 onHandleIntent,此函数中即是我们想要在 IntentService 中执行的任务。在函数执行结束后调用 stopSelf(msg.arg1) 终止服务,这也就是为什么任务执行完毕后会自动销毁的原因。
- onDestroy(): 在此方法中退出之前创建的线程,即:mServiceLooper.quit()。
boundService 三种使用方法
- 继承 Binder:实现内部类继承 Binder,并在 onBind() 中返回。此中方法不能实现 IPC。
- 使用 Messenger:Messenger 服务端需要传入 Handler 做参数,因此在 Service 中实现 Handler 内部类,创建 Messenger,并在 onBind() 中返回 mMessenger.binder。客户端通过 IBinder 作为参数新建 Messenger 实例,这样便可与服务端通信。Messenger 内部实现使用 Binder,支持 IPC,因此此中方式可用于跨进程通信。
- AIDL:新建 AIDL 文件,编译器会自动生成对于的 java 类,之后在 Service 实现自动生成类的接口方法,onBind() 方法中返回实现类的 asBinder() 方法,客户端中在 ServiceConnection 回调中通过 asInterface(IBinder) 获取到远端类通信。
关于 AIDL、Binder 的相关知识,为想单拿出一篇博客来说,所以这里就先简单说一下使用方法。欢迎关注我的微信公众平台(码小猪),如有更新会及时发布。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。