当前位置: 首页 > news >正文

kotlin与MVVM结合使用总结(三)

1. MVVM 架构详细介绍及源码层面理解

整体架构

MVVM(Model - View - ViewModel)架构是为了解决视图和数据模型之间的耦合问题而设计的。它通过引入 ViewModel 作为中间层,实现了视图和数据的分离,提高了代码的可维护性和可测试性。

  • View(视图层):在 Android 中,View 主要关联 Activity、Fragment 以及 XML 布局文件等,负责呈现界面与响应用户交互。像 Activity 里设置布局、初始化视图元素,以及处理用户点击等操作都属于 View 范畴。例如在一个登录界面 Activity 里,布局文件定义了输入框、按钮等 UI 元素的样式与位置,Activity 则处理按钮点击事件,这些都在 View 层完成。
  • Model(数据模型层):负责数据的获取、存储与处理。比如从网络请求用户信息、将数据存储到本地数据库等。在电商应用中,从服务器获取商品列表数据,或是将用户的购物车信息保存到本地数据库,都由 Model 层执行。
  • ViewModel(视图模型层):作为连接 View 与 Model 的纽带,承担关键的界面显示逻辑处理任务。它从 Model 获取数据,并将其转换为适合 View 展示的形式。例如在新闻应用中,Model 获取到原始新闻数据列表,ViewModel 可对数据进行加工,如截取新闻摘要、处理图片链接等,让数据能更好地在 View 中展示。在数据更新时,ViewModel 通过 LiveData 等机制通知 View 进行相应更新。从源码层面看,ViewModel 借助 ViewModelProvider 来创建与管理。ViewModelProvider 内部运用 ViewModelStore 存储 ViewModel 实例,确保配置变更(如屏幕旋转)时,ViewModel 实例不会被销毁,维持数据的稳定性。
观察者模式在 MVVM 中的应用

在 MVVM 架构里,观察者模式发挥着核心作用。ViewModel 持有数据,以 LiveData 为例,View 作为观察者监听 LiveData 数据变化。LiveData 内部维护了观察者列表,当数据变更时,会调用 dispatchingValue 方法遍历观察者列表。在 considerNotify 方法中,判断观察者状态,若活跃则通过 observer.mObserver.onChanged((T) mData) 通知观察者,View 接收到通知后更新界面,实现了 View 与 ViewModel 低耦合通信,这在诸多面试真题里都有涉及,是理解 MVVM 架构的关键。ViewModel 是通过 ViewModelProvider 来创建和管理的。

2. LiveData 实例化方法及源码分析

实例化方法
  • MutableLiveDataMutableLiveData 是 LiveData 的子类,它公开了 setValue() 和 postValue() 方法,允许外部修改其持有的数据。
MutableLiveData<String> liveData = new MutableLiveData<>();

在源码中,MutableLiveData 只是简单地继承了 LiveData 并暴露了修改数据的方法。

public class MutableLiveData<T> extends LiveData<T> {@Overridepublic void postValue(T value) {super.postValue(value);}@Overridepublic void setValue(T value) {super.setValue(value);}
}
  • 使用 Transformations 类进行转换Transformations 类提供了一些静态方法,如 map() 和 switchMap(),可以对 LiveData 进行转换。
LiveData<Integer> source = new MutableLiveData<>();
LiveData<String> transformed = Transformations.map(source, input -> "Transformed: " + input);

map() 方法的源码实现如下:

public static <X, Y> LiveData<Y> map(LiveData<X> source,final Function<X, Y> mapFunction) {final MediatorLiveData<Y> result = new MediatorLiveData<>();result.addSource(source, new Observer<X>() {@Overridepublic void onChanged(@Nullable X x) {result.setValue(mapFunction.apply(x));}});return result;
}

3. LiveData 如何实现生命周期绑定问题

LiveData 生命周期绑定机制在面试中频繁被问到,其实现依赖于 Android 的 Lifecycle 组件。

         当调用 LiveData.observe() 方法时,会创建 LifecycleBoundObserver 对象,它实现了 LifecycleEventObserver 接口来监听 LifecycleOwner(如 Activity、Fragment)的生命周期变化。在 observe() 方法源码中,先检查 LifecycleOwner 状态,若已销毁则直接返回;否则创建 LifecycleBoundObserver 并添加到观察者列表,同时将其注册到 LifecycleOwner 的生命周期观察者中。

public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {assertMainThread("observe");if (owner.getLifecycle().getCurrentState() == DESTROYED) {return;}LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);if (existing != null &&!existing.isAttachedTo(owner)) {throw new IllegalArgumentException("Cannot add the same observer"+ " with different lifecycles");}if (existing != null) {return;}owner.getLifecycle().addObserver(wrapper);
}

LifecycleBoundObserver 的 onStateChanged 方法会在 LifecycleOwner 生命周期状态变化时被调用。在此方法中,根据生命周期状态决定是否更新观察者。当状态变为 DESTROYED 时,从 LiveData 的观察者列表移除该观察者,防止内存泄漏;当状态为 STARTED 或 RESUMED 时,认为观察者活跃,可接收数据更新。

class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {@NonNullfinal LifecycleOwner mOwner;LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {super(observer);mOwner = owner;}@Overrideboolean shouldBeActive() {return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);}@Overridepublic void onStateChanged(@NonNull LifecycleOwner source,@NonNull Lifecycle.Event event) {if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {removeObserver(mObserver);return;}activeStateChanged(shouldBeActive());}@Overrideboolean isAttachedTo(LifecycleOwner owner) {return mOwner == owner;}@Overridevoid detachObserver() {mOwner.getLifecycle().removeObserver(this);}
}

这种机制确保 LiveData 仅在 LifecycleOwner 处于活跃状态(STARTED 或 RESUMED)时更新观察者,有效避免内存泄漏与空指针异常,是 LiveData 的重要特性。

4. LiveData 粘性事件的深入分析

粘性事件的概念

粘性事件是指当一个观察者注册到 LiveData 时,即使该 LiveData 在观察者注册之前已经有了更新,观察者仍然会接收到这些之前的更新。这是因为 LiveData 会记录最新的值,当有新的观察者注册时,会立即将最新的值发送给它。

源码层面分析

在 LiveData 的 observe() 方法中,当新的观察者注册时,会调用 dispatchingValue() 方法,该方法会检查观察者的状态,并将最新的值发送给它。

private void dispatchingValue(@Nullable ObserverWrapper initiator) {if (mDispatchingValue) {mDispatchInvalidated = true;return;}mDispatchingValue = true;do {mDispatchInvalidated = false;if (initiator != null) {considerNotify(initiator);initiator = null;} else {for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {considerNotify(iterator.next().getValue());if (mDispatchInvalidated) {break;}}}} while (mDispatchInvalidated);mDispatchingValue = false;
}private void considerNotify(ObserverWrapper observer) {if (!observer.mActive) {return;}if (!observer.shouldBeActive()) {observer.activeStateChanged(false);return;}if (observer.mLastVersion >= mVersion) {return;}observer.mLastVersion = mVersion;// 调用观察者的 onChanged 方法,发送最新的值observer.mObserver.onChanged((T) mData);
}

在 considerNotify() 方法中,会比较观察者的 mLastVersion 和 LiveData 的 mVersion,如果 mLastVersion 小于 mVersion,则会调用观察者的 onChanged() 方法,将最新的值发送给它。

解决粘性事件的方法

为了避免粘性事件的影响,可以考虑使用一些第三方库,如 SingleLiveEvent 或自定义 LiveData 实现。以下是一个简单的自定义 LiveData 实现,用于避免粘性事件:

import androidx.lifecycle.LiveData;import java.util.concurrent.atomic.AtomicBoolean;public class NonStickyLiveData<T> extends LiveData<T> {private final AtomicBoolean mPending = new AtomicBoolean(false);@Overridepublic void observeForever(@NonNull Observer<? super T> observer) {super.observeForever(new Observer<T>() {@Overridepublic void onChanged(T t) {if (mPending.compareAndSet(true, false)) {observer.onChanged(t);}}});}@Overridepublic void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {super.observe(owner, new Observer<T>() {@Overridepublic void onChanged(T t) {if (mPending.compareAndSet(true, false)) {observer.onChanged(t);}}});}@Overrideprotected void setValue(T value) {mPending.set(true);super.setValue(value);}@Overrideprotected void postValue(T value) {mPending.set(true);super.postValue(value);}
}

在这个自定义的 LiveData 中,使用 AtomicBoolean 来标记是否有新的值需要发送,只有当 mPending 为 true 时,才会调用观察者的 onChanged() 方法,从而避免了粘性事件的影响。

粘性事件总结

        在 LiveData 机制里,不活跃观察者(对应 LifecycleOwner 处于 STOPPED 或 PAUSED 状态)正常情况下不会接收数据更新事件。只有当观察者再次变为活跃状态时,LiveData 才会将最新数据发送给它。这是因为在 LifecycleBoundObserver 的 shouldBeActive 方法中,依据 LifecycleOwner 的当前生命周期状态判断观察者是否活跃,不活跃则不进行数据分发。

       然而,LiveData 存在粘性事件问题,这在面试中常被提及。粘性事件指新观察者注册时,即便 LiveData 之前已有更新,观察者仍会收到这些之前的更新数据。从源码层面分析,在 LiveData 的 observe() 方法中,新观察者注册后会调用 dispatchingValue() 方法。在 dispatchingValue() 内部的 considerNotify() 方法里,通过比较观察者的 mLastVersion 和 LiveData 的 mVersion 来决定是否通知观察者。若 mLastVersion 小于 mVersion,则调用观察者的 onChanged() 方法发送最新数据,导致粘性事件发生。

为解决粘性事件问题,常见方法如下:

  • 使用 SingleLiveEvent:自定义一个继承自 MutableLiveData 的类,重写相关方法确保事件只被消费一次。例如在一些开源项目中,SingleLiveEvent 类通过设置标志位,在 observe() 方法中判断标志位,仅在首次观察时触发数据更新,后续不再响应之前的粘性数据。
  • 使用 Event 包装类:将数据包装在 Event 类中,通过标记数据是否已被处理来避免重复触发。在观察者获取数据时,先检查标记位,若未处理则处理数据并设置标记位,防止重复处理粘性数据。
  • 使用 MediatorLiveDataMediatorLiveData 可监听其他 LiveData 变化,并在必要时过滤粘性事件。通过添加源 LiveData 的观察者,在数据变化时进行相应处理,如更新自身数据后移除源 LiveData,避免粘性事件传递给新观察者。

相关文章:

kotlin与MVVM结合使用总结(三)

1. MVVM 架构详细介绍及源码层面理解 整体架构 MVVM&#xff08;Model - View - ViewModel&#xff09;架构是为了解决视图和数据模型之间的耦合问题而设计的。它通过引入 ViewModel 作为中间层&#xff0c;实现了视图和数据的分离&#xff0c;提高了代码的可维护性和可测试性…...

前端基础之《Vue(11)—自定义指令》

一、自定义指令 1、自己封装指令 什么是指令&#xff1f;指令本质上就是DOM功能的一种抽象封装。 如果有一些DOM功能经常用&#xff0c;但是Vue没有提供相关指令&#xff0c;建议自己封装。 2、自定义全局指令 使用Vue.directive(指令名, function() {})定义全局指令。 3、…...

第3.2节 Android应用调用链路分析

3.2.1 Android调用链路简介 在Android应用程序中&#xff0c;调用链路涉及应用程序中不同组件&#xff08;如Activity、Service、BroadcastReceiver、ContentProvider&#xff09;之间的调用关系&#xff0c;以及应用程序与系统服务之间的交互。了解和分析这些调用链路对于调试…...

Codeforces Round 1019 (Div. 2) ABC

A 模拟 思路 数组y是不同的&#xff0c;且所以xi * yi 相同&#xff0c;只有x数组全不同才可以满足要求 代码 LL n,m,k;void solve() {map<LL,LL> mp;cin >> n;for (int i 1;i < n;i ){LL x;cin >> x;mp[x] ;}cout << mp.size() << endl;…...

Babylon.js 材质统一转换指南:将 AssetContainer 中的所有材质转换为 PBRMetallicRoughnessMaterial

在现代 3D 开发中&#xff0c;基于物理的渲染(PBR)已成为行业标准。本文将详细介绍如何在 Babylon.js 中将 AssetContainer 加载的各种材质统一转换为 PBRMetallicRoughnessMaterial&#xff0c;实现项目材质的标准化。 为什么需要材质转换&#xff1f; PBRMetallicRoughness…...

Linux Platform驱动模型全解析:从入门到精通

Linux Platform驱动模型全解析&#xff1a;从入门到精通 1. Platform驱动模型概述 1.1 什么是Platform驱动模型 Platform驱动模型是Linux内核为处理非热插拔设备&#xff08;通常是SoC集成外设&#xff09;而设计的一套驱动框架。它通过虚拟的"platform总线"将硬件…...

7.Excel:单元格格式

一 案例 1.案例1 2.案例2 3.案例3 二 三种基本数据类型 补充&#xff1a;在没有任何格式的情况下是这样对齐的。 1.文本 默认左对齐&#xff0c;文本不可参与计算。 2.数值 默认右对齐&#xff0c;数值计算精度是15位。 若超出15位&#xff0c;超出部分显示为0。 3.逻辑值 …...

文件传输过滤器绕过:Exe2Hex

Exe2hex是****g0tmilk开发的一款工具,您可以**在这里找到它。该工具将 EXE 文件转录为一系列十六进制字符串**,DEBUG.exe或Powershell可以将其还原为原始 EXE 文件。之后,该脚本会在受害者机器上运行,重建并执行 EXE 文件。这在系统管理员阻止EXE 文件传输或上传的****高级…...

从多类缺陷到高良率跃升|公差分析技术重构动力电池装配精度体系

在新能源汽车产业升级关键期&#xff0c;动力电池装配精度和因装配引起的安全问题已成为制约产能提升的核心瓶颈。某头部电池企业通过 CETOL 6σ 公差分析技术&#xff0c;成功构建了复杂电池系统的精度控制体系。生产实践表明&#xff0c;微观尺度的公差偏差可能引发系统性质量…...

QT开发技术【QT实现桌面右下角消息】

一、效果 ![ 二、弹窗主体部分 noticewidget /* ** File name: NoticeWidget.h ** Author: ** Date: 2025-04-25 ** Brief: 通知栏控件 ** Copyright (C) 1392019713qq.com All rights reserved. */#include "../Include/NoticeWidget.h"…...

【使用层次序列构建二叉树(数据结构C)】

使用层次序列构建二叉树&#xff08;C语言实现&#xff09; 在数据结构学习过程中&#xff0c;二叉树的构建方式通常有递归建树&#xff08;前序/中序&#xff09;和层次建树&#xff08;广度优先&#xff09;两种。本文将介绍一种基于辅助队列实现的层次建树方法&#xff0c;并…...

【基于Qt的QQ音乐播放器开发实战:从0到1打造全功能音乐播放应用】

&#x1f339; 作者: 云小逸 &#x1f91f; 个人主页: 云小逸的主页 &#x1f91f; motto: 要敢于一个人默默的面对自己&#xff0c;强大自己才是核心。不要等到什么都没有了&#xff0c;才下定决心去做。种一颗树&#xff0c;最好的时间是十年前&#xff0c;其次就是现在&…...

蓝桥杯 3. 密码脱落

密码脱落 原题目链接 题目描述 X 星球的考古学家发现了一批古代留下来的密码。 这些密码是由 A、B、C、D 四种植物的种子串成的序列。 仔细分析发现&#xff0c;这些密码串当初应该是前后对称的&#xff08;即镜像串&#xff09;。 由于年代久远&#xff0c;其中许多种子…...

数学基础 -- 欧拉恒等式的魅力:让复数旋转起来!

公式推导&#xff1a; e i π − 1 e^{i\pi} -1 eiπ−1 被誉为数学中最美的公式之一&#xff0c;它连接了五个数学中最重要的常数&#xff1a; e i π 1 0 (欧拉恒等式) e^{i\pi} 1 0 \tag{欧拉恒等式} eiπ10(欧拉恒等式) 这不仅是巧合&#xff0c;而是复数与三角函数…...

keil修改字体无效,修改字体为“微软雅黑”方法

在网上下载了微软雅黑字体&#xff0c;微软雅黑参考下载链接 结果在Edit->Configuration中找不到这个字体 这个时候可以在keil的安装目录中找到UV4/global.prop文件 用记事本打开它进行编辑&#xff0c;把字体名字改成微软雅黑 重新打开keil就发现字体成功修改了。 这个…...

LeetCode 每日一题 2845. 统计趣味子数组的数目

2845. 统计趣味子数组的数目 给你一个下标从 0 开始的整数数组 nums &#xff0c;以及整数 modulo 和整数 k 。 请你找出并统计数组中 趣味子数组 的数目。 如果 子数组 nums[l…r] 满足下述条件&#xff0c;则称其为 趣味子数组 &#xff1a; 在范围 [l, r] 内&#xff0c;设 …...

二进制兼容性分析方法

I. 引言 在软件工程领域&#xff0c;二进制兼容性&#xff08;Binary Compatibility&#xff09;是一个核心概念&#xff0c;它指的是一个计算系统能够运行为另一个系统编译的可执行代码&#xff08;通常是机器码&#xff09;的能力&#xff0c;而无需重新编译 。这与源代码兼…...

在 WSL 安装 OpenFOAM-12

在 WSL 安装 OpenFOAM-12 参考链接安装教程问题整理1、安装完成后运行测试算例 Alllrun 脚本报错 参考链接 OpenFOAM OpenFoam-v12 OpenFOAM-v12-Ubuntu 安装教程 直接在 OpenFOAM 官网找到 Down -> OpenFOAM v12 选择 DownLoad v12 | Ubuntu -> Read More 具体安装过…...

Linux-06 ubuntu 系统截图软件使用简单记录

文章目录 原委一、Shutter二、Flameshot三、Ksnip 原委 原先使用的 Flameshot 截图软件&#xff0c;在ubuntu 18.04下可以正常使用。 系统升级到22.04 后&#xff0c;安装后的只能截图&#xff0c;不能标注&#xff0c;想着修复下。 以下是个人备忘录记录&#xff0c;如何使用…...

基于python代码的通过爬虫方式实现快手发布视频(2025年4月)

1、将真实的快手创作服务平台的cookie贴到代码目录中kuaishou_cookie.txt文件里,运行python脚本即可; 2、运行之前根据import提示安装一些常见依赖,比如requests等; 3、__NS_sig3.js的源码见快手NS sig3签名算法(2025年1月)_快手sig3算法源码-CSDN博客 4、2025年4月份…...

人工智能与机器学习:Python从零实现逻辑回归模型

&#x1f9e0; 向所有学习者致敬&#xff01; “学习不是装满一桶水&#xff0c;而是点燃一把火。” —— 叶芝 我的博客主页&#xff1a; https://lizheng.blog.csdn.net &#x1f310; 欢迎点击加入AI人工智能社区&#xff01; &#x1f680; 让我们一起努力&#xff0c;共创…...

大模型助力嘉兴妇幼:数据分类分级的智能化飞跃

在医疗行业数字化转型进程中&#xff0c;数据已成为驱动服务升级与业务创新的核心要素。作为医疗行业数字化的探索者&#xff0c;嘉兴市妇幼保健院携手美创打造的智能化数据分类分级项目&#xff0c;数据识别率和分类分级率高达99%&#xff0c;分类分级准确率达90%&#xff0c;…...

MyBatisPlus文档

一、MyBatis框架回顾 使用springboot整合Mybatis,实现Mybatis框架的搭建 1、创建示例项目 (1)、创建工程 新建工程 创建空工程 创建模块 创建springboot模块 选择SpringBoot版本 (2)、引入依赖 <dependencies><dependency><groupId>org.springframework.…...

支持Function Call的本地ollama模型对比评测-》开发代理agent

目标是开发支持多个 Function 定义的智能体代理系统 ✅ 第一部分&#xff1a;是否支持多个函数&#xff08;multi-function calling&#xff09; 模型名称支持多个函数注册是否支持函数选择&#xff08;name 匹配&#xff09;是否能生成结构化参数OpenChat 3.5 / 3.5-0106✅&a…...

Docker拉取镜像代理配置实践与经验分享

Docker拉取镜像代理配置实践与经验分享 一、背景概述 在企业内网环境中&#xff0c;我们部署了多台用于测试与学习的服务器。近期&#xff0c;接到领导安排&#xff0c;需在其中一台服务器上通过Docker安装n8n应用程序。然而在实际操作过程中&#xff0c;遭遇Docker官方镜像库…...

Jinja 的详细介绍和学习方法

Jinja 是一种流行的 模板引擎&#xff08;Template Engine&#xff09;&#xff0c;主要用于生成动态的文本内容&#xff08;如 HTML、XML、配置文件等&#xff09;。它最初是为 Python 的 Web 框架&#xff08;如 Flask、Django&#xff09;设计的&#xff0c;但也可以独立使用…...

在 Windows 系统上升级 Node.js

一、查询电脑端已经安装的 Node.js 版本 1、通过【winR】 键&#xff0c;输入 cmd&#xff0c;点击【确定】按钮打开 cmd 窗口 2、命令行界面输入 node -v 查看目前 Node.js 版本 3、命令行界面输入 npm -v 查看目前 npm 版本 二、进入官网地址下载安装包 1、官网地址&#x…...

特斯拉宣布启动自动驾驶网约车测试,无人出租车服务进入最后准备阶段

特斯拉公司于4月24日正式宣布&#xff0c;已在美国得克萨斯州奥斯汀和加利福尼亚州旧金山湾区启动自动驾驶网约车服务的员工内部测试。这项测试将为今年夏季计划推出的完全无人驾驶出租车服务进行最后的验证和准备。 此次测试使用约200辆经过特殊改装的Model 3车型&#xff0c;…...

C++面试复习(7)2025.4.25

1&#xff0c;说一说常用的 Linux 命令(NIUKE) 1&#xff0c;cat 查看文件内容 cat filename2&#xff0c;rm 删除 rm filename&#xff1a;删除文件。 rm -r directory&#xff1a;删除目录及其内容。 rm -f filename&#xff1a;强制删除文件&#xff08;不询问确认&…...

使用 uv 工具快速创建 MCP 服务(Trae 配置并调用 MCP 服务)

文章目录 下载Traeuv 工具教程参考我的这篇文章创建 uv 项目main.pyTrae 配置 MCP 服务添加 MCP创建智能体 使用智能体调用 MCP 创建 demo 表查询 demo 表结构信息demo 表插入 2 条测试数据查询 demo 表中的数据 下载Trae https://www.trae.com.cn/ uv 工具教程参考我的这篇…...

07 Python 字符串全解析

文章目录 一. 字符串的定义二. 字符串的基本用法1. 访问字符串中的字符2. 字符串切片3. 字符串拼接4. 字符串重复5.字符串比较6.字符串成员运算 三. 字符串的常用方法1. len() 函数2. upper() 和 lower() 方法3. strip() 方法4. replace() 方法5. split() 方法 四. 字符串的进阶…...

IEEE期刊目录重磅更新!共242本期刊被收录!

&#x1f525; &#x1f525; &#x1f525; &#x1f525; 【IEEE期刊目录】 2025年2月&#xff0c;IEEE出版社更新了242本期刊目录&#xff0c;其中&#xff1a; • 完全OA期刊36本&#xff1a;SCI有6本&#xff0c;ESCI有15本&#xff1b; • 混合OA期刊183本&…...

微型计算机原理与接口技术第六版第四章课后习题答案-周荷琴,冯焕清-中国科学技术大学出版社

第六版书籍编排的第3章和第4章&#xff0c;仅这两章习题答案跟第四版的答案是相同的&#xff0c;可以参考第四版的答案 原第四版习题答案&#xff0c;蓝奏云&#xff1a; https://wwss.lanzouq.com/iWXOY1kvk3yf 第六版的第四章的习题我没有单独编辑&#xff0c;它是在上面第四…...

反爬策略应对指南:淘宝 API 商品数据采集的 IP 代理与请求伪装技术

一、引言​ 在电商数据驱动决策的时代&#xff0c;淘宝平台海量的商品数据极具价值。然而&#xff0c;淘宝为保障平台安全和用户体验&#xff0c;构建了严密的反爬体系。当采集淘宝 API 商品数据时&#xff0c;若不采取有效措施&#xff0c;频繁的请求极易触发反爬机制&#x…...

前端技术Ajax入门

1.1 AJAX 概念和 axios 使用 目标 了解 AJAX 概念并掌握 axios 库基本使用 讲解 1. 什么是 AJAX&#xff1f; 使用浏览器的 XMLHttpRequest 对象与服务器通信。在浏览器网页中&#xff0c;通过 AJAX 技术&#xff08;XHR 对象&#xff09;发起获取省份列表数据的请求&…...

【沉浸式求职学习day25】【部分网络编程知识分享】【基础概念以及简单代码】

不知道大家一直高强度学习自己是什么样的感觉&#xff0c;反正我现在逐渐变得麻木了&#xff0c;马上又要实习笔试了&#xff0c;每次笔试都要突击&#xff0c;每次突击都意识到自己有太多不会的&#xff0c;主打一个心累&#xff0c;但是又能怎样呢&#xff0c;自己选的路就是…...

聊聊Spring AI Alibaba的YoutubeDocumentReader

序 本文主要研究一下Spring AI Alibaba的YoutubeDocumentReader YoutubeDocumentReader community/document-readers/spring-ai-alibaba-starter-document-reader-youtube/src/main/java/com/alibaba/cloud/ai/reader/youtube/YoutubeDocumentReader.java public class You…...

常用第三方库:flutter_boost混合开发

常用第三方库&#xff1a;flutter_boost混合开发 前言 在移动应用开发中&#xff0c;混合开发是一个非常重要的话题。特别是对于已有原生应用想要引入Flutter的团队来说&#xff0c;如何实现Flutter页面和原生页面的无缝整合就显得尤为关键。本文将深入介绍flutter_boost这个…...

什么是 JSON?学习JSON有什么用?在springboot项目里如何实现JSON的序列化和反序列化?

作为一个学习Javaweb的新手&#xff0c;理解JSON的序列化和反序列化非常重要&#xff0c;因为它在现代Web开发&#xff0c;特别是Spring Boot中无处不在。 什么是 JSON&#xff1f; 首先&#xff0c;我们简单了解一下JSON (JavaScript Object Notation)。 JSON 是一种轻量级的…...

[mysql]数据类型精讲

目录 数据类型精讲: 整数类型 浮点类型 日期和时间类型 文本字符串类型 数据类型精讲: 精度问题:不能损失数据 性能问题:表的设计,范式的讲解. 表设计的时候需要设置字段,我们现在要把字段类型讲完.,细节点一点点给大家拆解. Float和double是有精度的损失的,这边推荐使用…...

WordPress AI插件能自动写高质量文章吗,如何用AI提升网站流量

WordPress AI插件能自动写高质量文章吗&#xff1f; 最近很多站长都在问&#xff0c;用wordpress AI插件真的能写出搜索引擎喜欢的好文章吗&#xff1f;作为一个用过10款AI写作工具的老站长&#xff0c;今天我就来分享真实使用体验&#xff0c;告诉你哪些插件好用、怎么用才能…...

【中级软件设计师】函数调用 —— 传值调用和传地址调用 (附软考真题)

【中级软件设计师】函数调用 —— 传值调用和传地址调用 (附软考真题) 目录 【中级软件设计师】函数调用 —— 传值调用和传地址调用 (附软考真题)一、历年真题二、考点&#xff1a;函数调用 —— 传值调用和传地址调用&#x1f53a;1、传值调用&#x1f53a;2、传引用(地址)调…...

ECMAScript 1(ES1):JavaScript 的开端

1. 版本背景与发布 ●发布时间&#xff1a;1997 年 6 月&#xff0c;由 ECMA International 正式发布&#xff0c;标准编号为 ECMA-262。 ●历史意义&#xff1a;ES1 是 JavaScript 的首个标准化版本&#xff0c;结束了 Netscape Navigator 与 Internet Explorer 浏览器间脚本语…...

C++入侵检测与网络攻防之暴力破解

目录 1.nessus扫描任务 2.漏洞信息共享平台 3.nessus扫描结果 4.漏扫报告的查看 5.暴力破解以及hydra的使用 6.crunch命令生成字典 7.其他方式获取字典 8.复习 9.关于暴力破解的防御的讨论 10.pam配置的讲解 11.pam弱密码保护 12.pam锁定账户 13.shadow文件的解析 …...

基于ssm的同城上门维修平台管理系统(源码+数据库)

54基于ssm的同城上门维修平台管理系统&#xff1a;前端jsp、jquery、bootstrap&#xff0c;后端 spring、mybatis&#xff0c;集成订单管理、商品管理、商品类型管理、商品浏览、购物车等功能于一体的系统。 ## 功能介绍 ### 用户 - 基本功能&#xff1a;登录、注册、退出、…...

力扣-hot100(和为k的子数组)

560. 和为 K 的子数组 中等 给你一个整数数组 nums 和一个整数 k &#xff0c;请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例 1&#xff1a; 输入&#xff1a;nums [1,1,1], k 2 输出&#xff1a;2 示例 2&#xff1a; 输入…...

【计算机视觉】CV实战 - 基于YOLOv5的人脸检测与关键点定位系统深度解析

基于YOLOv5的人脸检测与关键点定位系统深度解析 1. 技术背景与项目意义传统方案的局限性YOLOv5多任务方案的优势 2. 核心算法原理网络架构改进关键点回归分支损失函数设计 3. 实战指南&#xff1a;从环境搭建到模型应用环境配置数据准备数据格式要求数据目录结构 模型训练配置文…...

HTML word属性

介绍 CSS word-spacing 属性&#xff0c;用于指定段字之间的空间&#xff0c;例如&#xff1a; p {word-spacing:30px; }word-spacing属性增加或减少字与字之间的空白。 注意&#xff1a; 负值是允许的。 浏览器支持 表格中的数字表示支持该属性的第一个浏览器版本号。 属…...

Java—ThreadLocal底层实现原理

首先&#xff0c;ThreadLocal 本身并不提供存储数据的功能&#xff0c;当我们操作 ThreadLocal 的时候&#xff0c;实际上操作线程对象的一个名为 threadLocals 成员变量。这个成员变量的类型是 ThreadLocal 的一个内部类 ThreadLocalMap&#xff0c;它是真正用来存储数据的容器…...

GTSRB德国交通标志数据集下载以及训练集划分

GTSRB德国交通标志数据集下载以及训练集划分 一、数据集下载二、数据集划分 一、数据集下载 官网地址&#xff1a;附含数据集说明文档点击下载&#xff1a;训练数据集点击下载&#xff1a;测试数据集 二、数据集划分 在模型训练时&#xff0c;将训练数据集分成训练集和验证集&…...