Android: Service基本使用

Service 是 Android 四大组件之一。是实现程序后台运行的解决方案。

默认是运行主线程中。

基本使用流程

  1. 自定义 Service 继承 Service() 类, 必须重写唯一抽象方法 onBind()
  2. 为了 完成事情逻辑的处理,一般会重写 onCreate(), onStartCommand(), onDestroy() 方法
  3. 在 AndroidManifest.xml 中注册

分支一:启动、停止Service

  1. 使用显式 Intent 绑定自定义的Service;使用startService(intent)来启动Service

  2. 使用显式 Intent 绑定自定义的Service;使用stopService(intent)来停止Service

分支二:Activity 和 Service 进行通信--- Bind Service 的方式,让 Service 从一个"后台默默干活"的组件,变成一个"可以被前端控制"的对象。

  1. 自定义 Service
  • 内部创建 Binder 子类,用于暴露 Service 中需要被 Activity 调用的方法。

  • 重写 onBind(),返回该 Binder 实例。

  1. Activity 端
  • 实现 ServiceConnection 接口,重写 onServiceConnected (绑定时调用,里面有Binder类型的参数) 和 onServiceDisconnected (解绑时调用)。

  • 使用显式 Intent (指定 Service 的类名)调用 bindService()。

  • 在适当生命周期(如 onDestroy)调用 unbindService() 解绑。

Service 的生命周期

  • 整体生命周期回调 :onCreate(), onStartCommand(), onBind(), onUnbind(), onDestroy()。
    启动式:
text 复制代码
调用startService()方法 → onCreate() → onStartCommand() → ... → 调用stopService()/stopSelf()方法 → onDestroy()

需要注意的是,每次 startService(), onStartCommand() 都会执行,但是只有Service之前没有创建过,onCreate才会执行。

每个进程中每个Service只会存在一个实例,因此无论调用多少次 startService(),一次 stopService()/stopSelf()方法 Service 就会停止。

绑定式:

text 复制代码
调用bindService()方法 → onCreate() → onBind() → ... → 调用unbindService()方法 → onUnbind() → onDestroy()

销毁条件 :所有客户端都解绑 后,Service 会立即调用 onDestroy() 销毁(前提是没有被 startService 启动过)

onBind 只调用一次(除非 Service 被销毁重建) ,当第一个客户端绑定后,后续客户端再调用 bindService,如果 Service 当前还有其他客户端连着,则没有任何生命周期回调。

  • 当第一个客户端调用 bindService() 时,系统会:

    1. 检查该 Service 是否已启动(没有则调用 onCreate())

    2. 调用 onBind() 获取 IBinder 对象并返回给客户端

    3. 将这个 IBinder 缓存起来

  • 当第二个、第三个客户端再调用 bindService() 绑定同一个 Service(实例未销毁)时:

    • 系统直接复用之前缓存的 IBinder 对象

    • 不会再调用 onBind()

    • 新客户端直接获得那个 IBinder,可以立即与 Service 通信

混合式:

text 复制代码
startService()      → onCreate() → onStartCommand()
bindService()       → onBind()   (此时 Service 继续运行)
unbindService()     → onUnbind()  (但 Service 不会销毁,因为之前 startService 了)
stopService()       → onDestroy()

只有都解绑,或者停止后,才会onDestroy()回调。


前台Service

从 Android8.0 开始,只有前台可见的情况下,Service才能稳定运行,否则可能随时被系统回收。

为了使 Service 能够一直保持运行状态,使用通知的方式,将Service一直以通知的形式在状态栏显示,即保持在前台显示,以确保系统不会回收 Service。

可以视为: Service + 通知 + 权限声明

这里不是以 manager.notify(1, notification) 来显示通知,而是在 Service 中 onCreate 使用 startForeground(1,notification) 来显示前台 Service。

此次前台Service 需要 进行权限声明


多线程使用Service

因为Service默认是运行在主线程的,而Service一般会处理一些耗时逻辑,例如下载,很容易出现ANR(Application Not Responding)。 因此需要用到多线程技术.

方式:

  1. 在Service的每个具体方法开启一个子线程。例如 thread{}。
  2. 执行完逻辑后在 thread{} 中使用stopSelf()、stopService() 停止 Service 防止一直处于运行状态消耗系统资源

IntentService 是上述逻辑的一种Service封装类。

相关推荐
ao-weilai20 分钟前
MySQL数据库:基本查询
android·数据库·mysql
事圆则缓1 小时前
Kotlin 泛型方差实战:out、in、星投影与类型擦除
android·开发语言·kotlin
传奇开心果编程3 小时前
【Compose Multiplatform 跨端开发学与练】第5课 网络与数据层
android·网络·学习·ui·ios·kotlin·composer
ao-weilai4 小时前
MySQL数据库:内置函数
android·数据库·mysql
SWAGGY..4 小时前
【C++进阶】:(7)红黑树的原理与 C++ 实现:结构设计、插入调整及性质验证
android·java·开发语言·c++·算法
Android打工仔4 小时前
CoroutineScheduler 设计解析(上)—— 为什么 Dispatchers.IO 会创建更多线程?
android·kotlin·源码阅读
martindelophy5 小时前
用自然语言剪视频:我们在 Timeline Studio 中实现了 ChatCut 对话剪辑
android·音视频
ao-weilai6 小时前
MySQL数据库:复合查询
android·数据库·mysql
三少爷的鞋19 小时前
AI 时代,我们都将成为通才型开发者:只懂 Android,已经不够了
android
Dovis(誓平步青云)1 天前
家里设备越来越多,如何用一张空间地图控制灯光和温度![
android·java·前端·javascript·人工智能·电脑