【Android+多线程】IntentService 知识总结:应用场景 / 使用步骤 / 源码分析
定义
IntentService 是 Android中的一个封装类,继承自四大组件之一的Service
功能
处理异步请求 & 实现多线程
应用场景
线程任务 需 按顺序、在后台执行
- 最常见的场景:离线下载
- 不符合多个数据同时请求的场景:所有的任务都在同一个Thread looper里执行
使用步骤
步骤1:定义 IntentService的子类,需复写onHandleIntent()方法
步骤2:在Manifest.xml中注册服务
步骤3:在Activity中开启Service服务
步骤1:定义 IntentService的子类
传入线程名、复写
onHandleIntent()方法
public class myIntentService extends IntentService {/** * 在构造函数中传入线程名字**/ public myIntentService() {// 调用父类的构造函数// 参数 = 工作线程的名字super("myIntentService");}/** * 复写onHandleIntent()方法* 根据 Intent实现 耗时任务 操作**/ @Overrideprotected void onHandleIntent(Intent intent) {// 根据 Intent的不同,进行不同的事务处理String taskName = intent.getExtras().getString("taskName");switch (taskName) {case "task1":Log.i("myIntentService", "do task1");break;case "task2":Log.i("myIntentService", "do task2");break;default:break;}}@Overridepublic void onCreate() {Log.i("myIntentService", "onCreate");super.onCreate();}/** * 复写onStartCommand()方法* 默认实现 = 将请求的Intent添加到工作队列里**/ @Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Log.i("myIntentService", "onStartCommand");return super.onStartCommand(intent, flags, startId);}@Overridepublic void onDestroy() {Log.i("myIntentService", "onDestroy");super.onDestroy();}
}
步骤2:在Manifest.xml中注册服务
<service android:name=".myIntentService"><intent-filter ><action android:name="cn.scu.finch"/></intent-filter>
</service>
步骤3:在Activity中开启Service服务
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 同一服务只会开启1个工作线程// 在onHandleIntent()函数里,依次处理传入的Intent请求// 将请求通过Bundle对象传入到Intent,再传入到服务里// 请求1Intent i = new Intent("cn.scu.finch");Bundle bundle = new Bundle();bundle.putString("taskName", "task1");i.putExtras(bundle);startService(i);// 请求2Intent i2 = new Intent("cn.scu.finch");Bundle bundle2 = new Bundle();bundle2.putString("taskName", "task2");i2.putExtras(bundle2);startService(i2);startService(i); //多次启动}}
测试结果

对比
与Service对比

与普通线程对比

源码分析
IntentService的源码工作流程如下:

特别注意:若启动IntentService 多次,那么 每个耗时操作 则 以队列的方式 在 IntentService的 onHandleIntent回调方法中依次执行,执行完自动结束
接下来,我们将通过 源码分析 解决以下问题:
- IntentService 如何单独开启1个新的工作线程
- IntentService 如何通过onStartCommand() 将Intent 传递给服务 & 依次插入到工作队列中
问题1:IntentService如何单独开启1个新的工作线程
主要分析内容 = IntentService源码中的 onCreate()方法
@Override
public void onCreate() {super.onCreate();// 1. 通过实例化andlerThread新建线程 & 启动;故 使用IntentService时,不需额外新建线程// HandlerThread继承自Thread,内部封装了 LooperHandlerThread thread = new HandlerThread("IntentService[" + mName + "]");thread.start();// 2. 获得工作线程的 Looper & 维护自己的工作队列mServiceLooper = thread.getLooper();// 3. 新建mServiceHandler & 绑定上述获得Looper// 新建的Handler 属于工作线程 ->>分析1mServiceHandler = new ServiceHandler(mServiceLooper);
}/** * 分析1:ServiceHandler源码分析**/ private final class ServiceHandler extends Handler {// 构造函数public ServiceHandler(Looper looper) {super(looper);}// IntentService的handleMessage()把接收的消息交给onHandleIntent()处理@Overridepublic void handleMessage(Message msg) {// onHandleIntent 方法在工作线程中执行// onHandleIntent() = 抽象方法,使用时需重写 ->>分析2onHandleIntent((Intent)msg.obj);// 执行完调用 stopSelf() 结束服务stopSelf(msg.arg1);}
}/** * 分析2: onHandleIntent()源码分析* onHandleIntent() = 抽象方法,使用时需重写**/ @WorkerThreadprotected abstract void onHandleIntent(Intent intent);
问题2:IntentService 如何通过onStartCommand() 将Intent 传递给服务 & 依次插入到工作队列中
/** * onStartCommand()源码分析* onHandleIntent() = 抽象方法,使用时需重写**/ public int onStartCommand(Intent intent, int flags, int startId) {// 调用onStart()->>分析1onStart(intent, startId);return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}/** * 分析1:onStart(intent, startId)**/ public void onStart(Intent intent, int startId) {// 1. 获得ServiceHandler消息的引用Message msg = mServiceHandler.obtainMessage();msg.arg1 = startId;// 2. 把 Intent参数 包装到 message 的 obj 发送消息中,//这里的Intent = 启动服务时startService(Intent) 里传入的 Intentmsg.obj = intent;// 3. 发送消息,即 添加到消息队列里mServiceHandler.sendMessage(msg);
}
总结
从上面源码可看出:
IntentService本质 = Handler + HandlerThread
- 通过HandlerThread 单独开启1个工作线程:IntentService
- 创建1个内部 Handler :ServiceHandler
- 绑定 ServiceHandler 与 IntentService
- 通过 onStartCommand() 传递服务intent 到ServiceHandler 、依次插入Intent到工作队列中 & 逐个发送给 onHandleIntent()
- 通过onHandleIntent() 依次处理所有Intent对象所对应的任务
因此我们通过复写onHandleIntent() & 在里面 根据Intent的不同进行不同线程操作 即可
相关文章:
【Android+多线程】IntentService 知识总结:应用场景 / 使用步骤 / 源码分析
定义 IntentService 是 Android中的一个封装类,继承自四大组件之一的Service 功能 处理异步请求 & 实现多线程 应用场景 线程任务 需 按顺序、在后台执行 最常见的场景:离线下载不符合多个数据同时请求的场景:所有的任务都在同一个T…...
Python Tornado框架教程:高性能Web框架的全面解析
Python Tornado框架教程:高性能Web框架的全面解析 引言 在现代Web开发中,选择合适的框架至关重要。Python的Tornado框架因其高性能和非阻塞I/O特性而备受青睐。它特别适合处理大量并发连接的应用,比如聊天应用、实时数据处理和WebSocket服务…...
通过端口测试验证网络安全策略
基于网络安全需求,项目中的主机间可能会有不同的网络安全策略,这当然是好的,但很多时候,在解决网络安全问题的时候,同时引入了新的问题,如k8s集群必须在主机间开放udp端口,否则集群不能正常的运…...
Excel把其中一张工作表导出成一个新的文件
excel导出一张工作表 一个Excel表里有多个工作表,怎么才能导出一个工作表,让其生成新的Excel文件呢? 第一步:首先打开Excel表格,然后选择要导出的工作表的名字,比如“Sheet1”,把鼠标放到“She…...
第四份工作的环境配置
最近在内网中工作,会遇到不少的环境问题. 下面记录一下这个过程中的挑战: 环境:内网,连接不到外网. 如何配置开发环境: 方法0: 在服务器上安装环境. 但是服务器上没有相应的python包.因为python包是从外界获得的.并且,这些python包不能同步更新.所以,在服务器上直接搭建环…...
SpringBoot开发——Maven多模块工程最佳实践及详细示例
文章目录 一、前言二、Maven多模块工程的最佳实践1、项目结构清晰2、依赖管理统一3、插件配置统一4、版本控制一致5、模块间通信简化 三、详细示例1、项目结构2、父模块(parent)的pom.xml文件3、子模块(module-api)的pom.xml文件4…...
C 语言面向对象
面向对象的基本特性:封装,继承,多态 1.0 面向过程概念 当我们在编写程序时,通常采用以下步骤: 1. 将问题的解法分解成若干步骤 2. 使用函数分别实现这些步骤 3. 依次调用这些函数 这种编程风格的被称作 面向过程…...
无人机探测:光电侦测核心技术算法详解!
核心技术 双光谱探测跟踪: 可见光成像技术:利用无人机表面反射的自然光或主动光源照射下的反射光,通过高灵敏度相机捕捉图像。该技术适用于日间晴朗天气下的无人机探测,具有直观、易于识别目标的特点。 红外成像技术࿱…...
ffmpeg视频滤镜:替换部分帧-freezeframes
滤镜描述 freezeframes 官网地址 > FFmpeg Filters Documentation 这个滤镜接收两个输入,然后会将第一个视频中的部分帧替换为第二个视频的某一帧。 滤镜使用 参数 freezeframes AVOptions:first <int64> ..FV....... set first fra…...
PHP 超级全局变量
超级全局变量是指在php任意脚本下都可以使用 PHP 超级全局变量列表: $GLOBALS:是PHP的一个超级全局变量组,在一个PHP脚本的全部作用域中都可以访问。 $_SERVER:$_SERVER 是一个PHP内置的超级全局变量,它是一个包含了诸如头信息(header)、路…...
Pytorch使用手册-Tensors(专题二)
这段代码是对 PyTorch 中张量(Tensors)的详细介绍和操作演示。以下是逐步讲解: 1. 什么是张量 (Tensor) 张量是一种专门的数据结构,与 NumPy 的多维数组(ndarray)类似: 它可以在 GPU 或其他硬件加速器上运行。张量可以与 NumPy 共享内存,避免不必要的数据拷贝。它是为…...
centos安装小火车
平时没事闲着 装个小火车玩-------->>>>> yum install sl.x86_64 启动命令 sl 就会出现以下场景...
241125学习日志——[CSDIY] [InternStudio] 大模型训练营 [17]
CSDIY:这是一个非科班学生的努力之路,从今天开始这个系列会长期更新,(最好做到日更),我会慢慢把自己目前对CS的努力逐一上传,帮助那些和我一样有着梦想的玩家取得胜利!!&…...
sklearn中常用数据集简介
scikit-learn库中提供了包括分类、回归、聚类、降维等多种机器学习任务所需的常用数据集,方便进行实验和研究,它们主要被封装在sklearn.datasets中,本文对其中一些常用的数据集进行简单的介绍。 1.Iris(鸢尾花)数据集…...
机器学习在教育方面的应用文献综述
引言 随着大数据时代的到来,机器学习作为人工智能的一个重要分支,在教育领域展现出广泛的应用前景。本文综述了机器学习技术在教育领域的应用,包括个性化学习、智能评估、知识图谱构建等多个方面。 个性化学习 个性化学习是机器学习…...
滑动窗口最大值(java)
题目描述 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例 1: 输入:nums [1,3,-1,-3,5,3,6,7]…...
sklearn学习
介绍:scaler:换算的意思 1. 归一化MinMaxScaler() 归一化的意思是将一堆数,如果比较离散,为了让数据更适合模型训练,将离散的数据压缩到0到1之间,以方便模型更高效优质的学习,而对数据的预处理…...
Ubuntu下手动设置Nvidia显卡风扇转速
在Ubuntu下,您可以使用 NVIDIA显卡驱动程序提供的工具手动调整风扇转速。以下是详细步骤: 1. 确保已安装NVIDIA显卡驱动 确保系统已经安装了正确的NVIDIA驱动: nvidia-smi如果没有输出驱动信息,请先安装驱动: sudo…...
Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试
点一下关注吧!!!非常感谢!!持续更新!!! 大数据篇正在更新!https://blog.csdn.net/w776341482/category_12713819.html 目前已经更新到了: MyBatisÿ…...
ES 和Kibana-v2 带用户登录验证
1. 前言 ElasticSearch、可视化操作工具Kibana。如果你是Linux centos系统的话,下面的指令可以一路CV完成服务的部署。 2. 服务搭建 2.1. 部署ElasticSearch 拉取docker镜像 docker pull elasticsearch:7.17.21 创建挂载卷目录 mkdir /**/es-data -p mkdir /**/…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
C++中vector类型的介绍和使用
文章目录 一、vector 类型的简介1.1 基本介绍1.2 常见用法示例1.3 常见成员函数简表 二、vector 数据的插入2.1 push_back() —— 在尾部插入一个元素2.2 emplace_back() —— 在尾部“就地”构造对象2.3 insert() —— 在任意位置插入一个或多个元素2.4 emplace() —— 在任意…...
【工具教程】多个条形码识别用条码内容对图片重命名,批量PDF条形码识别后用条码内容批量改名,使用教程及注意事项
一、条形码识别改名使用教程 打开软件并选择处理模式:打开软件后,根据要处理的文件类型,选择 “图片识别模式” 或 “PDF 识别模式”。如果是处理包含条形码的 PDF 文件,就选择 “PDF 识别模式”;若是处理图片文件&…...
02-性能方案设计
需求分析与测试设计 根据具体的性能测试需求,确定测试类型,以及压测的模块(web/mysql/redis/系统整体)前期要与相关人员充分沟通,初步确定压测方案及具体的性能指标QA完成性能测试设计后,需产出测试方案文档发送邮件到项目组&…...
【Pandas】pandas DataFrame dropna
Pandas2.2 DataFrame Missing data handling 方法描述DataFrame.fillna([value, method, axis, …])用于填充 DataFrame 中的缺失值(NaN)DataFrame.backfill(*[, axis, inplace, …])用于**使用后向填充(即“下一个有效观测值”)…...
【系统架构设计师-2025上半年真题】综合知识-参考答案及部分详解(回忆版)
更多内容请见: 备考系统架构设计师-专栏介绍和目录 文章目录 【第1题】【第2题】【第3题】【第4题】【第5题】【第6题】【第7题】【第8题】【第9题】【第10题】【第11题】【第12题】【第13题】【第14题】【第15题】【第16题】【第17题】【第18题】【第19题】【第20~21题】【第…...
智能照明系统:具备认知能力的“光神经网络”
智能照明系统是物联网技术与传统照明深度融合的产物,其本质是通过感知环境、解析需求、自主决策的闭环控制,重构光与人、空间、环境的关系。这一系统由智能光源、多维传感器、边缘计算单元及云端管理平台构成,形成具备认知能力的“光神经网络…...
【Redis】Redis 的持久化策略
目录 一、RDB 定期备份 1.2 触发方式 1.2.1 手动触发 1.2.2.1 自动触发 RDB 持久化机制的场景 1.2.2.2 检查是否触发 1.2.2.3 线上运维配置 1.3 检索工具 1.4 RDB 备份实现原理 1.5 禁用 RDB 快照 1.6 RDB 优缺点分析 二、AOF 实时备份 2.1 配置文件解析 2.2 开启…...
