[划重点] Service 知识要点

代码星冰乐

专注成就未来

首页 归档 关于

[划重点] Service 知识要点

Jan 20, 2019 | ChanghuiN | Android | 阅读
文章目录
  1. 1. Service 三种启动方式
  2. 2. 生命周期
  3. 3. IntentService 原理
  4. 4. boundService 三种使用方法

作 者:ChanghuiN
原文链接:https://www.hchstudio.cn/article/2019/9f46/
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。


由于版权原因,请阅读原文 --> [划重点] Service 知识要点

关注我们

作 者:ChanghuiN
原文链接:https://www.hchstudio.cn/article/2019/9f46/
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。

作 者:ChanghuiN
原文链接:https://www.hchstudio.cn/article/2019/9f46/
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。

来总结一下 Service 的几个知识要点,包括启动方式、每种启动方式的生命周期、IntentService 源码分析,以及 boundService 三种使用方法。

Service 三种启动方式

  1. 前台 Service (startForegroundService(intent)): 在 API 大于等于 26 以上,用来设置通知栏。在调用这个 api 之后应马上调用 Service#startForeground(int, Notification),来设置 Notification,否则系统会自动停止 Service,并发生 ANR。

  2. 后台 Service (startService(intent)): 如果 app 的一些操作不需要通知用户,则启动后台 Service。

注:API 大于等于 26 时,当 app 不在前台的时候,后台服务会受到限制,这种情况下,官方文档推荐使用 Schedule jobs。

  1. 绑定 Service (bindService(intent, serviceConnection, flags)): 绑定 Service 提供客户端/服务端模式,组件之间可以用过它发送、接受消息,甚至可以跨进程通信。在调用 unbindService(),Service 就会销毁。

生命周期

startService(): onCreate() -> onStartCommand()/onStart() -> … -> onDestroy()
bindService(): onCreate() -> onBind() -> … -> onUnbind() -> onDestroy()
以上两个生命周期只是对单个 activity start 或者 bind 服务的时候,然而在实际使用的时候,通常会两个结合使用,也或者是多个 activity 对同一个 service 绑定。

  1. 多个 Activity StartService 时,Service 不会重复启动,onStartCommand() 会重复执行,并获取对应的 intent。当有一个 stopService() 时,Service 会销毁。
  2. 多个 Activity 绑定和解绑时,Service 会重复走 onBind()/onUnbind()这两个生命周期,但不会销毁,直到没有 Activity 和它有绑定关系的时候,才会销毁。
  3. 当 StartService/bindService 混合用时,Service 的销毁时机为 stopService。

service_binding_tree_lifecycle

IntentService 原理

大家都知道,IntentService 的特性是运行在非 UI 线程,可执行耗时操作,当执行完后会自动销毁。我们今天在看一下它的原理:
IntentService 内部由 HandlerThread 维护一个线程,在启动后获取 intent 并发送给 HandlerThread 所在的线程执行,执行完任务后自动调用 stopSelf() 销毁。
具体的源码实现如下:

  1. 继承 Service;
  2. onBind(): IntentService 由 startService() 启动,当然不需要 binder,所以这个函数返回 null;
  3. onCreate(): 新建 HandlerThread 并启动线程,通过 HandlerThread.getLooper() 新建 Handler。总结起来两句代码,大致如下:

    1
    2
    new HandlerThread().start();
    new ServiceHandler(thread.getLooper());
  4. onStart(): 这个函数中,通过前面新建的 Handler,把 intent 消息发送到非 UI 线程,即:mServiceHandler.sendMessage(msg)。

  5. ServiceHandler 的 handleMessage 函数实现中,先执行抽象函数 onHandleIntent,此函数中即是我们想要在 IntentService 中执行的任务。在函数执行结束后调用 stopSelf(msg.arg1) 终止服务,这也就是为什么任务执行完毕后会自动销毁的原因。
  6. onDestroy(): 在此方法中退出之前创建的线程,即:mServiceLooper.quit()。

boundService 三种使用方法

  1. 继承 Binder:实现内部类继承 Binder,并在 onBind() 中返回。此中方法不能实现 IPC。
  2. 使用 Messenger:Messenger 服务端需要传入 Handler 做参数,因此在 Service 中实现 Handler 内部类,创建 Messenger,并在 onBind() 中返回 mMessenger.binder。客户端通过 IBinder 作为参数新建 Messenger 实例,这样便可与服务端通信。Messenger 内部实现使用 Binder,支持 IPC,因此此中方式可用于跨进程通信。
  3. AIDL:新建 AIDL 文件,编译器会自动生成对于的 java 类,之后在 Service 实现自动生成类的接口方法,onBind() 方法中返回实现类的 asBinder() 方法,客户端中在 ServiceConnection 回调中通过 asInterface(IBinder) 获取到远端类通信。

关于 AIDL、Binder 的相关知识,为想单拿出一篇博客来说,所以这里就先简单说一下使用方法。欢迎关注我的微信公众平台(码小猪),如有更新会及时发布。

关注我们

作 者:ChanghuiN
原文链接:https://www.hchstudio.cn/article/2019/9f46/
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。

分享
Android源码解析
ArrayBlockingQueue 阻塞队列Pika 性能优化
微信关注我们
分类
  • Android8
  • Go4
  • Java59
  • Kafka,Java1
  • Kotlin2
  • Linux1
  • MapReduce1
  • Python2
  • Raft1
  • Redis1
  • ThreadPoolExecutor1
  • go1
  • 工具1
  • 总结8
  • 旅游日记1
标签
Nginx ChanghuiN haifeiWu Android Java 设计模式 hexo Kotlin 算法 MySQL 源码解析 Python Redis golang web Kafka 配置中心 总结 性能优化 旅游日记 Shell Go 问题排查 译文 Docker Spring Boot 工具 学习笔记 WebFlux 性能测试 go 散列表 源码 netty Raft
最近文章
  • Kafka的日志复制机制
  • 从20到21
  • go 并发编程
  • 【译】了解Linux CPU负载-您何时应该担心?
  • Zookeeper 与分布式锁
  • 基于Redis的分布式锁到底安全吗?
  • 【译】Raft 学生指南
  • ThreadPoolExecutor 的简单梳理
  • MapReduce 的简单实现
  • 使用 Map 实现策略模式
福利专区
    免费SSL证书
      阿里云红包
        腾讯云专属福利
        Copyright © 2021 代码星冰乐. Powered by ChanghuiN. 版权所有 晋ICP备15001365号
        特别感谢: 云服务器服务商 、 CDN 服务商