Android学习总结之service篇

引言

在 Android 开发里,Service 与 IntentService 是非常关键的组件,它们能够让应用在后台开展长时间运行的操作。不过,很多开发者仅仅停留在使用这两个组件的层面,对其内部的源码实现了解甚少。本文将深入剖析 Service 和 IntentService 的源码,揭示它们的工作原理与区别。

Service 源码剖析

1. Service 概述

Service 是 Android 四大组件之一,用于在后台执行长时间运行的操作,且不提供用户界面。它可以通过 startService() 启动,也能通过 bindService() 绑定,从而与其他组件进行交互。

2. 生命周期方法

Service 的生命周期方法定义在 android.app.Service 类中,主要包含 onCreate()onStartCommand()onBind() 和 onDestroy()

Service
├─ onCreate()          // 初始化(仅一次)
├─ onStartCommand()    // 处理 startService 请求(可多次调用)
├─ onBind()            // 处理 bindService 请求(返回 IBinder)
├─ onDestroy()         // 释放资源
└─ 需手动管理子线程    // 耗时操作需自行创建线程
  • onCreate():服务创建时调用,通常用于初始化操作,此方法仅调用一次。
  • onStartCommand():每次调用 startService() 启动服务时都会调用该方法,其返回值决定了服务在被系统杀死后的重启策略。
  • onBind():当调用 bindService() 时调用,需要返回一个 IBinder 对象,用于与服务进行通信。
  • onDestroy():服务销毁时调用,可用于释放资源。
A[Service 生命周期] --> B[onCreate()]B --> C{启动方式}C -->|startService()| D[onStartCommand()]C -->|bindService()| E[onBind()]D --> F[手动调用 stopSelf()/stopService()]E --> G[解绑时 onUnbind()]F & G --> H[onDestroy()]I[IntentService 生命周期] --> J[onCreate()]J --> K[创建 HandlerThread & ServiceHandler]K --> L[onStartCommand() 调用 onStart()]L --> M[ServiceHandler 处理 Message]M --> N[调用 onHandleIntent(intent)(子线程)]N --> O[自动调用 stopSelf()]O --> P[onDestroy()(Looper.quit())]

3. 启动流程

当调用 startService() 方法时,最终会调用到 ActivityManagerService 中的相关方法,它会负责创建 Service 实例并调用其生命周期方法。

// ActivityManagerService.java
public ComponentName startService(IApplicationThread caller, Intent service,String resolvedType, int userId) {// 处理启动服务的逻辑synchronized(this) {// ...ServiceRecord r = startServiceLocked(caller, service, resolvedType, callingPid,callingUid, userId);// ...}// ...
}

4. 注意事项

Service 默认在主线程中运行,若在 Service 中执行耗时操作,会导致界面卡顿。因此,若有耗时操作,应在 Service 中手动创建子线程。

IntentService 源码剖析

1. IntentService 概述

IntentService 是 Service 的子类,它是一个异步的、会自动停止的服务。它内部使用 HandlerThread 创建了一个子线程,所有的 Intent 都会在这个子线程中处理。

2. 关键源码分析

IntentService(继承 Service)
├─ onCreate()          
│  └─ 创建 HandlerThread(子线程)
│  └─ 获取 Looper,创建 ServiceHandler(绑定子线程 Looper)
├─ onStartCommand()    
│  └─ 调用 onStart(),将 Intent 封装为 Message 发送给 ServiceHandler
├─ ServiceHandler(Handler 子类)
│  └─ handleMessage():调用 onHandleIntent() 处理 Intent,调用 stopSelf()
├─ onHandleIntent()     // 开发者需实现的核心业务逻辑(在子线程执行)
└─ onDestroy()         └─ 调用 Looper.quit() 终止子线程
// android.app.IntentService
public abstract class IntentService extends Service {private volatile Looper mServiceLooper;private volatile ServiceHandler mServiceHandler;private String mName;private boolean mRedelivery;private final class ServiceHandler extends Handler {public ServiceHandler(Looper looper) {super(looper);}@Overridepublic void handleMessage(Message msg) {onHandleIntent((Intent)msg.obj);stopSelf(msg.arg1);}}public IntentService(String name) {super();mName = name;}@Overridepublic void onCreate() {super.onCreate();HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");thread.start();mServiceLooper = thread.getLooper();mServiceHandler = new ServiceHandler(mServiceLooper);}@Overridepublic void onStart(@Nullable Intent intent, int startId) {Message msg = mServiceHandler.obtainMessage();msg.arg1 = startId;msg.obj = intent;mServiceHandler.sendMessage(msg);}@Overridepublic int onStartCommand(@Nullable Intent intent, int flags, int startId) {onStart(intent, startId);return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;}@Overridepublic void onDestroy() {mServiceLooper.quit();}@Override@Nullablepublic IBinder onBind(Intent intent) {return null;}protected abstract void onHandleIntent(@Nullable Intent intent);
}

3. 关键流程

  • onCreate():创建一个 HandlerThread 并启动它,然后获取该线程的 Looper,创建一个 ServiceHandler 并关联该 Looper
  • onStartCommand():调用 onStart() 方法,将传递的 Intent 封装成 Message 发送给 ServiceHandler
  • ServiceHandler 的 handleMessage():调用 onHandleIntent() 方法处理 Intent,处理完成后调用 stopSelf() 停止服务。

4. 特点总结

  • 异步处理:所有的 Intent 都会在子线程中处理,避免了在主线程中执行耗时操作。
  • 自动停止:当所有的 Intent 处理完成后,IntentService 会自动调用 stopSelf() 方法停止服务。
  • 顺序处理IntentService 会按照 Intent 到达的顺序依次处理,不会并发处理多个 Intent

Service 与 IntentService 的区别

1. 线程方面

  • Service 默认在主线程中运行,若要执行耗时操作,需手动创建子线程。
  • IntentService 内部创建了一个子线程,所有的 Intent 都会在该子线程中处理。

2. 停止方式

  • Service 需要手动调用 stopSelf() 或 stopService() 来停止服务。
  • IntentService 在处理完所有的 Intent 后会自动停止。

3. 处理方式

  • Service 可以同时处理多个请求。
  • IntentService 会按顺序依次处理 Intent,不会并发处理。

总结图表

特性ServiceIntentService
继承关系直接继承 ContextWrapper,实现 ComponentCallbacks2继承自 Service,是 Service 的子类
线程环境默认运行在主线程(UI 线程),需手动创建子线程处理耗时任务内部创建 HandlerThread 子线程,通过 ServiceHandler 在子线程处理所有 Intent
启动后的处理逻辑需重写 onStartCommand,手动处理业务逻辑,需手动调用 stopSelf() 停止服务自动将 Intent 封装为 Message,通过 ServiceHandler 按顺序处理,处理完自动停止
生命周期控制需手动调用 stopService() 或 stopSelf() 停止,或通过 onStartCommand 返回值控制重启策略无需手动停止,处理完所有 Intent 后自动调用 stopSelf() 停止
并发处理可同时处理多个 startService 请求(需自行处理多线程同步)按 Intent 接收顺序串行处理,同一时间仅处理一个 Intent
默认 onBind 返回值返回 null(需开发者自定义 IBinder直接返回 null(不支持绑定,如需绑定需自定义子类)
适用场景复杂后台逻辑(如跨组件通信、长期运行任务)简单异步任务(如网络请求、文件操作),任务完成后自动停止

结论

        若需要执行简单的异步任务且任务完成后自动停止服务,可选择 IntentService;若需要与其他组件进行交互或同时处理多个请求,则可选择 Service

感谢观看!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/76173.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ExternalProject_Add 使用手册与文档详解

一、基本概念与语法 ExternalProject_Add 是 CMake 的一个核心命令,用于在构建过程中集成和管理外部项目(如第三方库)。它支持完整的生命周期管理,包括下载、配置、构建、安装和测试。 语法: ExternalProject_Add(&l…

低延迟云网络的核心技术

低延迟云网络通过架构优化、协议创新、硬件加速等多维度技术手段,将数据传输延迟降低至毫秒级甚至微秒级。 1. 网络架构优化 1.1 扁平化网络Leaf-Spine 架构 减少网络层级,缩短数据转发路径(如数据中心内部一跳可达)。 扁平化网络Leaf-Spine(叶子-脊椎)架构是一种现代…

网络安全法规与入门指南

在当今数字化时代,网络安全已成为保障个人隐私、企业利益和国家安全的关键领域。随着网络攻击的日益复杂和频繁,了解和遵守网络安全法规变得尤为重要。本文将深入探讨网络安全相关法规,并为想要进入这一领域的读者提供实用的入门指南。 一、…

硬盘分区格式方案之 MBR(Master Boot Record)主引导记录的 主分区 和 扩展分区 笔记250407

硬盘分区格式方案之 MBR(Master Boot Record)主引导记录的 主分区 和 扩展分区 笔记250407 一、主分区(Primary Partition) 1. 定义与功能 直接引导操作系统:主分区是独立的存储单元,可直接安装操作系统并…

【Proteus仿真】【32单片机-A007】PT100热敏温度检测系统设计

目录 一、主要功能 二、使用步骤 三、硬件资源 四、软件设计 五、实验现象 联系作者 一、主要功能 1、LCD1602显示当前检测的温度值以及温度阈值 2、超过上限温度,降温模块启动​ 3、PT100热敏电阻测量-60C-135C 4、按键设置温度阈值 5、超过阈值&#xff0…

pyqt SQL Server 数据库查询-优化2

1、增加导出数据功能 2、增加删除表里数据功能 import sys import pyodbc from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QListWidget, QLineEdit, QPushButton, \QTableWidget, QTableWidgetItem, QLabel, QMessageBox from PyQt6.QtGui i…

Github 热点项目 ChartDB AI自动导表结构+迁移脚本,3分钟生成专业数据库关系图

ChartDB堪称数据库设计神器!亮点①:动动手指输入SQL,秒出结构图,表关系一目了然,团队评审时再也不用画图两小时。亮点②:AI智能转换超贴心,MySQL转PostgreSQL只需点个按钮,跨平台迁移…

地质科研智能革命:当大语言模型“扎根”地质现场、大语言模型本地化部署与AI智能体协同创新实践

在地质学迈向“深时数字地球”(Deep-time Digital Earth)的进程中,传统研究方法正面临海量异构数据(地质图件、遥感影像、地震波谱等)的解析挑战。大语言模型(LLM)与AI智能体的本地化部署技术&a…

DAPP实战篇:使用web3.js连接合约

说明 本系列内容目录:专栏:区块链入门到放弃查看目录 如果你还没有创建好项目请先查看:《DApp实战篇:先用前端起个项目》,如果你还不知道web3.js是什么请先查看:《DApp实战篇:前端技术栈一览》。 安装 点此查看web3.js官方文档 打开项目根目录,并唤起终端: 键入w…

源代码保密解决方案

背景分析 随着各行各业业务数据信息化发展,各类产品研发及设计等行业,都有关乎自身发展的核心数据,包括业务数据、源代码保密数据、机密文档、用户数据等敏感信息,这些信息数据有以下共性: — 属于核心机密资料&…

dolphinscheduler单机部署链接oracle

部署成功请给小编一个赞或者收藏激励小编 1、安装准备 JDK版本:1.8或者1.8oracle版本:19Coracle驱动版本:8 2、安装jdk 下载地址:https://www.oracle.com/java/technologies/downloads/#java8 下载后上传到/tmp目录下。 然后执行下面命…

2025-04-08 NO.4 Quest3 交互教程

文章目录 1 环境准备2 新手指引:Building Blocks2.1 创建 OVR 相机2.2 创建交互功能2.3 创建交互物体 3 老手开发:Interaction SDK3.1 创建交互功能3.2 创建交互物体 4 UI 交互4.1 3D 按钮4.2 Unity UI ​ 新版 Meta SDK(v74)优化…

关于Spring MVC中@RequestMapping注解的详细解析,涵盖其核心功能、属性、使用场景及最佳实践

以下是关于Spring MVC中RequestMapping注解的详细解析,涵盖其核心功能、属性、使用场景及最佳实践: 1. 基础概念 RequestMapping是Spring MVC的核心注解,用于将HTTP请求映射到控制器(Controller)的方法上。它支持类级…

Scala 异常处理

Scala 异常处理 引言 Scala 是一门多范式编程语言,它结合了面向对象和函数式编程的特性。在软件开发过程中,异常处理是保证程序稳定性和可靠性的重要环节。本文将深入探讨 Scala 中的异常处理机制,包括异常的抛出、捕获和处理策略。 异常概述 什么是异常? 在计算机编程…

PyTorch:解锁AI新时代的钥匙

(前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站)。 揭开PyTorch面纱 对于许多刚开始接触人工智能领域的朋友来说,PyTorch这个名字或许既熟悉又陌生。…

React-06React中refs属性(字符串refs,回调形式,React.createRef() )

1.React中refs属性 绑定到render输出的任何组件上&#xff0c;通过this.ref.绑定名直接操作DOM元素或获取子组件的实例。 2.绑定refs实例 2.1 字符串refs(已经过时参考官网API) 字符串(string)的ref存在一定的效率问题 <input refinput1 type"text" placehole…

五子棋游戏开发:静态资源的重要性与设计思路

以下是以CSDN博客的形式整理的关于五子棋游戏静态资源需求的文章&#xff0c;基于我们之前的讨论&#xff0c;内容结构清晰&#xff0c;适合开发者阅读和参考。我尽量保持技术性、实用性&#xff0c;同时加入一些吸引读者的亮点。 五子棋游戏开发&#xff1a;静态资源的重要性与…

c编译和c++编译有什么区别?

文章目录 c编译和c编译有什么区别多态函数重载虚函数表 vtable 输入输出同步类型检查模板和特化链接 C 标准库 C 能编译 C 的代码吗&#xff1f; c编译和c编译有什么区别 多态 函数重载 C 支持多个同名函数&#xff08;参数不同&#xff09;&#xff0c;这是编译期多态 编译…

无缝集成Docker与Maven:docker-maven-plugin实战指南

关于 docker-maven-plugin 的详细介绍和使用指南&#xff0c;帮助你在 Maven 项目中实现 Docker 镜像的自动化构建、推送和管理。 1. 插件的作用 docker-maven-plugin 是一个 Maven 插件&#xff0c;允许在 Maven 构建生命周期中直接集成 Docker 操作&#xff0c;例如&#xf…

智能仓储数字孪生Demo(Unity实现)

一、项目背景与行业痛点 医药流通行业仓储管理面临三大核心挑战&#xff1a; 合规性风险&#xff1a;GSP&#xff08;药品经营质量管理规范&#xff09;对温湿度、药品批次追溯的严苛要求&#xff0c;传统人工记录易出错效率瓶颈&#xff1a;库区布局复杂&#xff0c;人工巡检…