android lifeCycleOwner生命周期
一 Fragment中 viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) 什么时候执行?
让我分析一下相关问题:
- 关于 onPause 时的数据更新:
viewLifecycleOwner.lifecycleScope.launch {viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {// 数据收集代码}
}
repeatOnLifecycle(Lifecycle.State.STARTED)
意味着
只在 Fragment 处于 STARTED 状态(在 onStart 之后,onPause 之前)时才会收集数据- 当 Fragment 执行 onPause 时,数据收集会暂停,不会更新 UI
- 这是正确的行为,因为不应该在后台更新不可见的 UI
- 关于 onDestroyView 后的状态恢复:
private val tempViewModel: TemperatureViewModel by viewModels()
private val fanViewModel: FanViewModel by viewModels()
private val sharedViewModel: SharedViewModel by activityViewModels()
viewModels()
delegate 会在 Fragment 的生命周期内保持 ViewModel 实例activityViewModels()
delegate 会在 Activity 的生命周期内保持 ViewModel 实例- ViewModel 的状态会在配置更改(如屏幕旋转)时自动保持
- 即使 Fragment 的 View 被销毁,ViewModel 仍然存活,保持着最新状态
- 当 Fragment 重新创建 View 时,会使用同一个 ViewModel 实例,因此状态自动恢复
- 数据恢复流程:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)initView()collectUiState() // 重新开始收集数据
}
- 当 Fragment 重新创建 View 时,会重新调用 collectUiState()
- ViewModel 中的 StateFlow/Flow 会发送最新状态
- UI 会立即更新到最新状态
这种实现方式是合理的,因为:
- 遵循了 Android 生命周期安全原则
- 避免了在后台不必要的 UI 更新
- 保证了状态的可靠性和一致性
- 有效处理了配置更改场景
二 为什么viewModel在view销毁,仍能存活,保存着ui状态?
delegate
确实是代理的含义。让我解释 viewModels()
delegate 的工作原理:
- Delegate 机制:
private val viewModel: MyViewModel by viewModels()
by
关键字表示使用 Kotlin 的属性代理viewModels()
返回一个ViewModelLazy
对象- 代理负责处理 ViewModel 的实例化和获取
- ViewModelLazy 工作原理:
class ViewModelLazy<VM : ViewModel>(private val viewModelClass: KClass<VM>,private val storeProducer: () -> ViewModelStore,private val factoryProducer: () -> ViewModelProvider.Factory
) : Lazy<VM> {private var cached: VM? = nulloverride val value: VMget() {val viewModel = cachedreturn if (viewModel == null) {val factory = factoryProducer()val store = storeProducer()ViewModelProvider(store, factory).get(viewModelClass.java).also {cached = it}} else {viewModel}}
}
- ViewModel 存活原理:
- Fragment 持有对
ViewModelStore
的引用 ViewModelStore
是一个简单的 HashMap,用于存储 ViewModel 实例ViewModelStore
与 Fragment 的生命周期解耦,不随 View 的销毁而销毁- 只有在 Fragment 真正被销毁时(如 Activity 被销毁),
ViewModelStore
才会清理
- 配置更改时的行为:
Fragment 重建 ─→ ViewModelStore 保持存活
↓ ↓
新的 View 原有 ViewModel 实例
↓ ↓
重新绑定数据 状态保持不变
优点:
- 延迟初始化 - 只在首次访问时创建 ViewModel
- 生命周期安全 - 自动处理 ViewModel 的创建和清理
- 状态保持 - 在配置更改时保存数据
- 内存管理 - 适时清理不需要的 ViewModel 实例
这就是为什么即使在 View 销毁或屏幕旋转时,ViewModel 仍能保持状态的技术原理。
三 android中 activity和viewModel生命周期的区别是什么
在 Android 的架构中,Activity
和 ViewModel
有着不同的生命周期管理机制,这是 MVVM 架构中实现 UI 状态持久化和解耦的核心基础。
✅ 一、Activity 与 ViewModel 生命周期的区别
对象 | 生命周期谁管理 | 生命周期范围 | 销毁时机 |
---|---|---|---|
Activity | 系统管理(与 UI 生命周期强绑定) | 短暂(屏幕旋转、返回键等都会销毁) | 屏幕旋转、按返回键、系统回收 |
ViewModel | ViewModelStore 管理(由 ViewModelProvider 创建) | 绑定到 Activity / Fragment 的生命周期 | 所依附的 Activity 或 Fragment 销毁后才销毁 |
✅ 二、为什么 Activity 销毁了 ViewModel 才销毁?
因为 ViewModel
是为“配置更改下的数据持久化”设计的组件,Android 会:
- 在屏幕旋转(或语言切换等配置更改)时,销毁旧的
Activity
实例,创建一个新的。 - 但 ViewModel 被托管在
ViewModelStore
中,不跟随Activity
的配置变更销毁。 - 直到 Activity 真正 finish 或被系统 kill,ViewModel 才销毁。
👉 这意味着:
屏幕旋转只是临时销毁了 UI,但 ViewModel 仍然活着。
✅ 三、为什么 ViewModel 可以持久化 UI 状态?
因为 ViewModel 的职责就是存储并管理界面相关的数据,且生命周期长于 Activity:
- 它存在于
Activity
或Fragment
的作用域内,但 不会因配置更改而销毁。 - 所以可以在 ViewModel 中存储 UI 状态(如输入框内容、选中项、滚动位置等)。
- 当新的 Activity 创建时,通过同一个
ViewModelProvider
获取原有 ViewModel,数据依然存在!
🎯 举个例子:
class MyViewModel : ViewModel() {val userName = MutableLiveData<String>()
}
在 Activity 中使用:
val viewModel = ViewModelProvider(this)[MyViewModel::class.java]viewModel.userName.observe(this) {// 更新 UI
}
即使屏幕旋转,Activity 重建了,但 viewModel
是同一个,userName
依旧保留!
✅ 四、深入原理:ViewModel 如何“活得更久”?
- Android Framework 在配置变化时,会:
- 暂时保存
ViewModelStore
和SavedStateRegistry
。 - 销毁旧 Activity 并创建新 Activity。
- 将旧的
ViewModelStore
重新附加给新 Activity。
- ViewModel 保存在
ViewModelStore
,而不是在 Activity 实例里。
所以:
Activity 重建 ≠ ViewModel 重建
✅ 五、ViewModel 销毁时机总结:
Activity.finish()
或被系统 kill,才会销毁 ViewModel。- Fragment 的 ViewModel 也可以作用域更长(如绑定到父 Activity)。
ViewModel
的onCleared()
方法会在真正销毁时调用,可释放资源。
✅ 六、补充:如果希望屏幕旋转后也保持 UI 状态,有三种方式对比:
方法 | 是否推荐 | 说明 |
---|---|---|
onSaveInstanceState() | ✅ 可选 | 保存轻量级 UI 状态(如文本、位置) |
ViewModel | ✅ 推荐 | 保存更大或复杂的数据结构,且与 UI 解耦 |
Room/DB | ✅ 长期存储 | 跨进程或跨 Activity 的持久状态 |
四 viewModel什么时候销毁?
屏幕旋转时,Activity 的确会被销毁,但这并不等价于我们手动调用的 Activity.finish()
方法。这两者在 Android Framework 中有重要区别。
✅ 关键理解:屏幕旋转导致的是“配置更改销毁”,不是调用 finish()
当屏幕旋转发生时:
系统会执行:
1. 销毁旧的 Activity 实例(onDestroy() 被调用)
2. 创建一个新的 Activity 实例(走 onCreate())
但这 并不是调用了代码中的 finish()
方法,而是 Android 框架内部处理配置变化的一个机制。它不会触发真正的「完全生命周期终结」,而是带有保留机制的销毁。
✅ 为什么 ViewModel 不被销毁?
背后的机制是:
- 每个
Activity
背后都有一个ViewModelStore
。 - 当因配置变化(如旋转)导致 Activity 被销毁时,Android 会临时保存旧的
ViewModelStore
。 - 然后,新 Activity 被创建时,从保存的
ViewModelStoreOwner
重新获取旧的 ViewModel 实例。
这个行为是由 ViewModelProvider
和 SavedStateViewModelFactory
等底层机制共同支持的。
✅ 更形象地理解:
假设旋转屏幕时发生了如下变化:
旧的 Activity(A1):
ViewModelStore 里存着 MyViewModel旋转后创建新的 Activity(A2):
系统会把 A1 的 ViewModelStore 传递给 A2A2 调用 ViewModelProvider(this)[MyViewModel::class.java] 时,
得到的是 A1 中的同一个 ViewModel 实例
因此:
- ViewModel 没有被销毁。
- ViewModel 里的数据依然存在。
- 看到 UI 状态得以“保留”。
✅ 那 ViewModel 什么情况下才会销毁?
ViewModel 生命周期取决于它所绑定的 ViewModelStoreOwner
,比如 Activity
或 Fragment
:
情况 | ViewModel 会销毁吗? |
---|---|
屏幕旋转(配置更改) | ❌ 不会 |
手动调用 finish() | ✅ 会 |
用户点击返回键退出 Activity | ✅ 会 |
系统因资源不足杀死进程 | ✅ 会 |
Fragment detach 且不复用 | ✅ 会 |
✅ 所以总结:
- 屏幕旋转 ≠ finish(),虽然
onDestroy()
会被调用,但属于“可恢复销毁”。 - ViewModel 被设计为适应这种情况,并保留数据,避免 UI 状态丢失。
- ViewModel 的生命周期由 ViewModelStore 控制,不直接绑定 Activity 的内存生命周期。
五 Fragment 关联的 ViewModel 的销毁时机。
1. Fragment ViewModel 的两种作用域
Fragment 可以使用两种方式创建 ViewModel:
// 1. Fragment 作用域的 ViewModel
private val fragmentViewModel: MyViewModel by viewModels()// 2. Activity 作用域的 ViewModel
private val activityViewModel: SharedViewModel by activityViewModels()
2. Fragment作用域 ViewModel 的销毁时机
Fragment 作用域的 ViewModel 在以下情况会销毁:
class MyFragment : Fragment() {private val viewModel by viewModels<MyViewModel>()override fun onDestroy() {super.onDestroy()// Fragment 真正销毁时,ViewModel 也会销毁}
}
销毁场景:
- Fragment 被移除且不再复用
- 宿主 Activity 被销毁(非配置变更导致的销毁)
- Fragment detach 且不会再次 attach
不会销毁的场景:
- Fragment 视图销毁(onDestroyView)
- 屏幕旋转等配置变更
- Fragment 被替换但加入了返回栈
3. Activity作用域 ViewModel 的销毁时机
class MyFragment : Fragment() {private val sharedViewModel by activityViewModels<SharedViewModel>()// Activity 销毁时才会销毁,Fragment 的生命周期变化不影响
}
销毁场景:
- 宿主 Activity finish
- 系统回收 Activity
- 用户按返回键退出 Activity
4. 实际示例
class MyFragment : Fragment() {// Fragment 作用域 ViewModelprivate val fragmentViewModel by viewModels<MyViewModel>()// Activity 作用域 ViewModelprivate val sharedViewModel by activityViewModels<SharedViewModel>()override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {// Fragment view 创建return inflater.inflate(R.layout.fragment_my, container, false)}override fun onDestroyView() {super.onDestroyView()// View 销毁,ViewModel 仍然存活}override fun onDestroy() {super.onDestroy()// Fragment 销毁,fragmentViewModel 销毁// 但 sharedViewModel 仍然存活}
}
5. ViewModel 清理机制
class MyViewModel : ViewModel() {override fun onCleared() {super.onCleared()// ViewModel 销毁时执行清理工作// 取消协程// 释放资源}
}
6. 注意事项
- 防止内存泄漏:
class MyViewModel : ViewModel() {private val coroutineScope = CoroutineScope(Dispatchers.Main + Job())override fun onCleared() {coroutineScope.cancel() // 清理协程super.onCleared()}
}
- 视图引用:
class MyViewModel : ViewModel() {// 错误:不要持有 View 引用private lateinit var binding: FragmentBinding// 正确:使用 LiveData/StateFlow 通知 UIprivate val _state = MutableStateFlow<UiState>()val state = _state.asStateFlow()
}
7. 总结
Fragment ViewModel 的销毁时机取决于:
- 使用的作用域(Fragment 还是 Activity)
- Fragment/Activity 的真实生命周期结束
- 非配置变更导致的销毁
理解这些销毁时机对于:
- 正确管理资源
- 避免内存泄漏
- 实现合适的数据共享
非常重要。
六 判断Fragment是否被销毁
Fragment 调用 onDestroy()
不一定意味着 Fragment 被永久移除。让我详细解释:
Fragment 的几种销毁情况
- 配置变更时的临时销毁:
class MyFragment : Fragment() {private val viewModel by viewModels()override fun onDestroy() {super.onDestroy()// 配置变更时会调用,但 ViewModel 不会销毁}
}
- 真正的永久销毁:
// Activity 中
supportFragmentManager
.beginTransaction()
.remove(fragment) // 移除 Fragment
.commit()
- 加入返回栈的销毁:
supportFragmentManager
.beginTransaction()
.replace(R.id.container, NewFragment())
.addToBackStack(null) // Fragment 被替换但可返回
.commit()
判断是否真正销毁的方式
class MyFragment : Fragment() {override fun onDestroy() {super.onDestroy()when {// 1. 检查是否是配置变更activity?.isChangingConfigurations == true -> {// ViewModel 不会销毁}// 2. 检查是否在返回栈中isRemoving && !requireActivity().isFinishing -> {if (fragmentManager?.backStackEntryCount ?: 0 > 0) {// Fragment 在返回栈中,ViewModel 不会销毁} else {// Fragment 被永久移除,ViewModel 会销毁}}// 3. Activity 正在销毁requireActivity().isFinishing -> {// Fragment 和 ViewModel 都会销毁}}}
}
Fragment ViewModel 的销毁时机
class MyFragment : Fragment() {private val viewModel by viewModels()// ViewModel 会在以下情况销毁:// 1. Fragment 被永久移除fragmentManager.beginTransaction().remove(this).commit()// 2. 宿主 Activity 被销毁activity?.finish()// 3. Fragment detach 且不会重新 attachfragmentManager.beginTransaction().detach(this).commit()
}
关键判断条件
override fun onDestroy() {super.onDestroy()val isReallyDestroying = when {// 配置变更不算真正销毁activity?.isChangingConfigurations == true -> false// Fragment 被移除且不在返回栈中isRemoving && fragmentManager?.backStackEntryCount == 0 -> true// Activity 结束activity?.isFinishing == true -> trueelse -> false}if (isReallyDestroying) {// ViewModel 会在这种情况下销毁}
}
总结:
onDestroy()
被调用不等于 Fragment 被永久移除- 需要考虑配置变更、返回栈和 Activity 状态
- ViewModel 只在 Fragment 真正不再使用时才销毁
相关文章:
android lifeCycleOwner生命周期
一 Fragment中 viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) 什么时候执行? 让我分析一下相关问题: 关于 onPause 时的数据更新: viewLifecycleOwner.lifecycleScope.launch {viewLifecycleOwner.repeatOnLifecycle(Lifecycle.Sta…...
高防IP能抗住500G攻击吗?
在当今互联网环境中,网络安全问题日益严峻,尤其是针对网站的DDoS攻击,更是让众多站长头疼不已。而高防IP作为应对此类攻击的有效手段,其性能与稳定性成为了大家关注的焦点。那么,高防IP真的能抗住500G的超大流量攻击吗…...
工作流引擎-10-什么是 BPM?
工作流引擎系列 工作流引擎-00-流程引擎概览 工作流引擎-01-Activiti 是领先的轻量级、以 Java 为中心的开源 BPMN 引擎,支持现实世界的流程自动化需求 工作流引擎-02-BPM OA ERP 区别和联系 工作流引擎-03-聊一聊流程引擎 工作流引擎-04-流程引擎 activiti 优…...

day1-小白学习JAVA---JDK安装和环境变量配置(mac版)
JDK安装和环境变量配置 我的电脑系统一、下载JDK1、oracle官网下载适合的JDK安装包,选择Mac OS对应的版本。 二、安装三、配置环境变量1、终端输入/usr/libexec/java_home -V查询所在的路径,复制备用2、输入ls -a3、检查文件目录中是否有.bash_profile文…...
每日温度(力扣-739)
【题目描述】 给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。 【输出输出样…...
QT中子线程触发主线程弹窗并阻塞等待用户响应-传统信号槽实现
目录 QT中子线程触发主线程弹窗并阻塞等待用户响应传统信号槽实现实现思路具体步骤1. 定义信号与槽2. 异步任务中触发弹窗3. 主线程处理弹窗4. 连接信号与槽关键点总结 更简单实现 QT中子线程触发主线程弹窗并阻塞等待用户响应 传统信号槽实现 场景需求:在子线程执…...
HarmonyOS鸿蒙系统深度运维指南
一、开发与调试环境全链路配置 工具链部署标准流程 HDC 3.0调试套件:支持分布式设备的跨端调试与性能分析,需配置端口转发规则(默认调试端口:8080)KaihongOS桌面开发环境:集成DevEco Studi…...
SpringBoot多租户系统的5种架构设计方案
多租户(Multi-tenancy)是一种软件架构模式,允许单个应用实例服务于多个客户(租户),同时保持租户数据的隔离性和安全性。 通过合理的多租户设计,企业可以显著降低运维成本、提升资源利用率,并实现更高效的服务交付。 本文将分享S…...

数据分析实战1(Excel制作报表)
Excel数据链接:【课程4.0】第2章_Excel.zip - 飞书云文档 1、拿到数据第一步 备份数据 ctrlshiftL:筛选 相关快捷键:(alt:自动求和、ctrlshift5:转换为%) 2、环比、同比 环比(本…...

本地部署大模型llm+RAG向量检索问答系统 deepseek chatgpt
项目视频讲解: 本地部署大模型llm+RAG向量检索问答系统 deepseek chatgpt_哔哩哔哩_bilibili 运行结果:...
设备健康管理的战略升维:用预测性维护重构企业竞争力
第一章 传统维护的沉默成本:被低估的利润黑洞 当轴承振动值突破安全阈值时,制造企业损失的远非维修费用。某重型装备制造厂的案例揭示了典型多米诺效应:传动系统突发故障导致36小时停产,触发订单违约金(合约金额的9%&…...
Redis事务详解:原理、使用与注意事项
文章目录 Redis事务详解:原理、使用与注意事项什么是Redis事务Redis事务的基本使用基本事务示例事务执行过程 Redis事务的错误处理1. 入队错误2. 执行错误 WATCH命令:乐观锁实现Redis事务的局限性事务的最佳实践Lua脚本总结 Redis事务详解:原…...
提升 GitHub Stats 的 6 个关键策略
哈哈,GitHub 的 “B-” 评级 其实是个玄学问题,但确实有一些 快速提升的技巧!你的数据看起来 提交数(147)和 PR(9)不算少,但 Stars(21)和贡献项目数ÿ…...
CSS Animation 详解
CSS Animation 允许元素平滑地从一个样式状态过渡到另一个样式状态。通过设置关键帧(keyframes),可以控制动画序列中的中间步骤。 一、核心概念 1.关键帧(Keyframes) 使用 keyframes 规则定义动画序列通过百分比或 …...

LabVIEW 中内存释放相关问题
在LabVIEW 编程领域,内存管理是一个关键且复杂的议题。我们常常关注 LabVIEW 如何将内存释放回操作系统(OS),以及是否有方法确保在特定数据结构(如队列、变体属性、动态数据引用 DVR 等)销毁、删除或清空后…...
【HarmonyOS 5】鸿蒙中的UIAbility详解(三)
【HarmonyOS 5】鸿蒙中的UIAbility详解(三) 一、前言 本文是鸿蒙中的UIAbility详解系列的最终章。主要针对UIAbility的冷启动和热启动,对于want数据的处理。UIAbility的备份恢复,UIAbility的接续等高级功能的概念和使用讲解。 …...

基于内存高效算法的 LLM Token 优化:一个有效降低 API 成本的技术方案
在使用 OpenAI、Claude、Gemini 等大语言模型 API 构建对话系统时,开发者普遍面临成本不断上升的挑战。无论是基于检索增强生成(RAG)的应用还是独立的对话系统,这些系统都需要维护对话历史以确保上下文的连贯性,类似于…...
vue-11(命名路由和命名视图)
命名路由和命名视图 命名路由和命名视图提供了组织和导航 Vue.js 应用程序的强大方法,尤其是在它们的复杂性增加时。它们提供了一种语义更合理、可维护的路由方法,使您的代码更易于理解和修改。命名路由允许您按名称引用路由,而不是依赖 URL…...
(附代码)自定义 LangChain 文档分割器,深入探索 LangChain 文档分割策略与应用
自定义文档分割器 在 LangChain 中,如果内置的文档分割器均没办法完成需求,还可以根据特定的需求实现自定义文档分割器(一般极少),实现的方法也非常简单,继承文本分割器基类 TextSplitter,在构造…...

Python打卡训练营Day42
DAY 42 Grad-CAM与Hook函数 知识点回顾 回调函数lambda函数hook函数的模块钩子和张量钩子Grad-CAM的示例 作业:理解下今天的代码即可 import torch import torch.nn as nn import torch.nn.functional as F import torchvision import torchvision.transforms as tr…...

基于微信小程序的scratch学习系统
博主介绍:java高级开发,从事互联网行业六年,熟悉各种主流语言,精通java、python、php、爬虫、web开发,已经做了六年的毕业设计程序开发,开发过上千套毕业设计程序,没有什么华丽的语言࿰…...
MATLAB实战:机器学习分类回归示例
以下是一个使用MATLAB的Statistics and Machine Learning Toolbox实现分类和回归任务的完整示例代码。代码包含鸢尾花分类、手写数字分类和汽车数据回归任务,并评估模型性能。 %% 加载内置数据集 % 鸢尾花数据集(分类) load fisheriris; X_i…...
动态库导出符号与extern “C“
1. windows下动态库导出符号 根据C/C语法规则,函数声明中的修饰符(如__declspec(dllexport))可以放在返回类型之前或返回类型之后、函数名之前。这两种方式在功能上是等价的,编译器会以相同的方式处理。 __declspec(dllexport) …...
小知识:STM32 printf 重定向(串口输出)--让数据 “开口说话” 的关键技巧
引言 在 C 语言开发中,printf函数是我们调试程序、输出数据的得力助手,它能将格式化的数据输出到标准输出设备(通常是屏幕)。然而,在嵌入式领域,STM32 单片机并没有默认的显示设备,要让printf函…...
`docker commit` 和 `docker save`区别
理解 docker commit 和 docker save 之间的区别对于正确管理 Docker 镜像非常重要。让我们详细解释一下这两个命令的作用及其区别。 1. docker commit 作用: docker commit roop-builder roop:v1 命令的作用是基于一个正在运行的容器 roop-builder 创建一个新的镜…...

【C++ 多态】—— 礼器九鼎,釉下乾坤,多态中的 “风水寻龙诀“
欢迎来到一整颗红豆的博客✨,一个关于探索技术的角落,记录学习的点滴📖,分享实用的技巧🛠️,偶尔还有一些奇思妙想💡 本文由一整颗红豆原创✍️,感谢支持❤️!请尊重原创…...

SCSAI平台面向对象建模技术的设计与实现
一、核心设计思想 SCSAI平台的核心目标是通过元建模(Meta-Modeling)技术实现面向对象建模的零编码化。其核心思想为: 自反性设计:定义ObjectClassInfo (OCI)为元类(Meta-Class),所有对象类均为…...

pikachu通关教程-CSRF
CSRF(get) 用bp进行抓包 选择action value值的修改 点击test in browser copy然后放在bp代理的浏览器上,会出现一个提交按钮,这时候点击之后信息就被修改了。 CSRF(post) 请求的方式不同,其他都是一样 CSRF Token 存在cookie 首先要先下载一…...

智能体觉醒:AI开始自己“动手”了-自主进化开启任务革命时代
1. 智能体:AI从“工具”到“伙伴”的关键跃迁 1.1 什么是智能体? 智能体(Agent)是AI的“进化版”——它不再局限于生成文字或图像,而是能像人类一样“规划任务”“调用工具”甚至“协同合作”。例如,一个…...
Python爬虫实战:研究Aiohttp库相关技术
1. 引言 1.1 研究背景与意义 随着互联网的快速发展,网络上的数据量呈爆炸式增长。爬虫作为一种自动获取网络信息的工具,在数据挖掘、信息检索、舆情分析等领域有着广泛的应用。传统的同步爬虫在面对大量 URL 时效率低下,无法充分利用现代计算机的多核资源和网络带宽。而异…...