【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 /**/…...

CodeIgniter如何手动将模型连接到数据库
在CodeIgniter中,模型通常是自动与数据库连接的,因为模型类(CI_Model)已经内置了对数据库操作的支持。但是,如果你需要手动指定数据库连接或者进行一些特殊的数据库配置,你可以通过几种方式来实现。 1. 使…...

商用密码应用安全性评估,密评整体方案,密评管理测评要求和指南,运维文档,软件项目安全设计相关文档合集(Word原件)
一、 密码应用安全性评估方案 (一) 密码应用测评工作思路 1.1.1. 测评准备活动的主要任务 1.1.2. 测评准备活动的输出文档 1.2. 方案编制活动 1.2.1. 方案编制活动的主要任务 1.2.2. 方案编制活动的输出文档 1.3. 现场预评估活动 1.3.1. 现场测评…...

AI赋能电商:构建高效、智能化的新零售生态
随着人工智能(AI)技术的不断进步,其在电商领域的应用日益广泛,从购物推荐到供应链管理,再到商品定价,AI正在全面改变传统电商的运营模式,并推动行业向智能化和精细化方向发展。本文将探讨如何利…...

【GAMES101笔记速查——Lecture 19 Cameras,Lenses and Light Fields】
本章节内容:相机、棱镜、光场 计算机图形学的两种成像方法: 1.合成方法:光栅化、光线追踪(展示出现实没有的东西) 2.捕捉方法:相机(捕捉现实已有的东西) 目录 1 相机 1.1 针孔相…...

虚拟机上搭建达梦DSC简略步骤
vmware 17 centos 7.6 达梦 dm8_20240920_x86_rh7_64.iso cd /d C:\Program Files (x86)\VMware\VMware Workstation\.\vmware-vdiskmanager.exe -c -s 100MB -a lsilogic -t 2 "F:\vm\dmdsc\sharedisk\share-dcr.vmdk" .\vmware-vdiskmanager.exe -c -s 100MB -a l…...

Python和R荧光分光光度法
🌵Python片段 Python在处理荧光分光光度法数据方面非常强大,得益于其丰富的数据处理和可视化库,可以轻松实现从数据读取到分析的完整流程。荧光分光光度法用于测量物质在激发光照射下发出的荧光强度,常用于定量分析和特性研究。 …...

电子学习中的关键游戏化元素
游戏化彻底改变了电子学习领域,提供了一种使学习具有吸引力、互动性和有效性的方法。通过将类似游戏的功能集成到教育平台中,教育工作者可以增强动力,提高知识记忆,并创造动态的学习体验。游戏化的关键要素为设计与学习者产生共鸣…...

算法日记 33 day 动态规划(打家劫舍,股票买卖)
今天来看看动态规划的打家劫舍和买卖股票的问题。 上题目!!!! 题目:打家劫舍 198. 打家劫舍 - 力扣(LeetCode) 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金…...

JavaScript的let、var、const
这张图片主要介绍了JavaScript中的三种变量声明方式:let、var和const。 1. let 含义:let是现在实际开发中常用的变量声明方式。特点: 块级作用域:let声明的变量只在其所在的块级作用域内有效。例如:{let x 10; } co…...

C语言-数学基础问题
一.奇数、偶数问题 1.从键盘上输入一个整数,判断并输出它是奇数还是偶数。 //从键盘上输入一个整数,判断并输出它是奇数还是偶数。 main() {int i;printf("输入一个整数:\n");scanf("%d",&i);if(i%20)printf("它是偶数\n…...