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

Android学习总结之Glide篇(缓存和生命周期)

一、Glide缓存

1. 内存缓存

内存缓存主要包含活动资源缓存与 LRU 内存缓存这两个级别。

活动资源缓存(Active Resources)
  • 作用:用于存放当前正在被显示的图片资源。当某张图片正展示在 ImageView 上时,它会被纳入活动资源缓存,防止重复加载相同图片。
  • 源码分析:在 Engine 类里,activeResources 是一个 WeakReference 类型的集合,用来存储活动资源。图片加载完成并显示时,Engine 的 activate 方法会将图片资源存入活动资源缓存:
// Engine.java
// 将图片资源放入活动资源缓存
void activate(Key key, EngineResource<?> resource) {// 确保在主线程执行Util.assertMainThread(); // 创建一个弱引用,指向要存入缓存的图片资源ActiveResources.ResourceWeakReference toPut =new ActiveResources.ResourceWeakReference(key, resource, getReferenceQueue());// 将弱引用存入活动资源缓存集合,若存在相同键的弱引用则返回旧的ActiveResources.ResourceWeakReference removed = activeResources.put(key, toPut); if (removed != null) {// 若有旧的弱引用,重置它removed.reset(); }
}

当图片不再显示时,Engine 的 deactivate 方法会将其从活动资源缓存中移除:

// Engine.java
// 从活动资源缓存中移除图片资源
@Nullable 
EngineResource<?> deactivate(Key key) {Util.assertMainThread();// 从活动资源缓存集合中移除指定键的弱引用ActiveResources.ResourceWeakReference removed = activeResources.remove(key); if (removed != null) {// 若移除的弱引用不为空,重置它,并返回对应的图片资源removed.reset(); return removed.getResource();}return null;
}
LRU 内存缓存(LRU Memory Cache)
  • 作用:作为内存缓存的第二级,当活动资源缓存中没有所需图片时,会在此查找。LRU 算法会优先剔除最近最少使用的图片,以合理利用缓存空间。
  • 源码分析MemoryCacheAdapter 类借助 LruCache 实现 LRU 内存缓存,LruCache 是 Android 提供的基于 LRU 算法的缓存类。MemoryCacheAdapter 的 put 方法用于将图片资源存入 LRU 内存缓存:
// MemoryCacheAdapter.java
// 将图片资源存入 LRU 内存缓存
@Override
public void put(Key key, EngineResource<?> resource) {cache.put(key, resource);
}

get 方法用于从 LRU 内存缓存中获取图片资源:

// MemoryCacheAdapter.java
// 从 LRU 内存缓存中获取图片资源
@Override
@Nullable
public EngineResource<?> get(Key key) {return cache.get(key);
}

2. 磁盘缓存

磁盘缓存分为原始图片缓存和转换后图片缓存两个级别。

原始图片缓存(Disk Cache Original)
  • 作用:用于存储从网络或本地文件系统下载的原始图片。当内存缓存中没有图片时,会先检查原始图片缓存。
  • 源码分析DiskLruCacheWrapper 类实现了磁盘缓存的操作。put 方法用于将原始图片数据写入磁盘缓存:
// DiskLruCacheWrapper.java
// 将原始图片数据写入磁盘缓存
@Override
public void put(Key key, Writer writer) {DiskLruCache.Editor editor = null;try {// 获取用于写入磁盘缓存的编辑器editor = cache.edit(getKeyForDiskCache(key)); if (editor == null) {throw new IllegalStateException("Had two simultaneous puts for: " + key);}// 将图片数据写入缓存,并根据写入结果决定提交或放弃写入if (writer.write(editor.newOutputStream(0))) { editor.commit();} else {abortQuietly(editor);}} catch (IOException e) {// 出现异常时放弃写入abortQuietly(editor); }
}

get 方法用于从磁盘缓存中读取原始图片数据:

// DiskLruCacheWrapper.java
// 从磁盘缓存中读取原始图片数据
@Override
@Nullable
public File get(Key key) {DiskLruCache.Snapshot snapshot = null;try {// 获取磁盘缓存中指定键的快照snapshot = cache.get(getKeyForDiskCache(key)); if (snapshot != null) {// 若快照存在,返回对应的文件return snapshot.getFile(0); }} catch (IOException e) {// 出现异常不做处理} finally {if (snapshot != null) {// 无论是否读取成功,关闭快照snapshot.close(); }}return null;
}
转换后图片缓存(Disk Cache Transformed)
  • 作用:用于存储经过 Glide 转换(如裁剪、缩放、模糊等)后的图片。当要显示经过转换的图片时,会先检查此缓存。
  • 源码分析:转换后图片缓存的实现和原始图片缓存类似,同样通过 DiskLruCacheWrapper 类操作。不同的是,存储和读取时使用的键会依据图片的转换操作计算,以保证不同转换后的图片能正确缓存和读取。

3. 缓存查找顺序

当使用 Glide 加载图片时,缓存查找顺序如下:

  1. 活动资源缓存(Active Resources)
  2. LRU 内存缓存(LRU Memory Cache)
  3. 转换后图片缓存(Disk Cache Transformed)
  4. 原始图片缓存(Disk Cache Original)
  5. 网络或本地文件系统

在 Engine 类的 load 方法中实现了上述查找顺序。先从活动资源缓存找,若没有则找 LRU 内存缓存,接着找转换后图片缓存和原始图片缓存,都没有时才从网络或本地文件系统获取。这种多级缓存机制和特定的查找顺序,能有效提高图片加载效率,减少不必要的资源获取操作,提升应用性能和用户体验

二、Glide的生命周期

1. 生命周期管理的入口

在 Android 应用中使用 Glide 加载图片,常见代码如 Glide.with(this).load(url).into(imageView)。这里的 Glide.with() 方法是 Glide 生命周期管理的起始点,它会依据传入参数(Activity、Fragment 等)的类型进行不同处理。

// Glide.java
// 根据传入的 Activity 获取 RequestManager
public static RequestManager with(@NonNull Activity activity) {// 调用 getRetriever 方法获取 RequestManagerRetriever 实例,再调用其 get 方法获取 RequestManagerreturn getRetriever(activity).get(activity); 
}// 根据传入的 FragmentActivity 获取 RequestManager
public static RequestManager with(@NonNull FragmentActivity activity) {return getRetriever(activity).get(activity);
}// 根据传入的 Fragment 获取 RequestManager
public static RequestManager with(@NonNull Fragment fragment) {// 先通过 fragment.getContext() 获取上下文,再获取 RequestManagerRetriever 实例并调用其 get 方法return getRetriever(fragment.getContext()).get(fragment); 
}

getRetriever() 方法返回的 RequestManagerRetriever 实例负责创建或获取 RequestManagerRequestManager 是 Glide 中管理图片请求的核心类,它能根据 Activity 或 Fragment 的生命周期来控制图片请求的启动、暂停和取消。

2. RequestManagerRetriever 的作用

RequestManagerRetriever 的主要职责是为传入的 Activity 或 Fragment 创建或获取对应的 RequestManager。它通过添加一个隐藏的 FragmentSupportRequestManagerFragment)来监听 Activity 或 Fragment 的生命周期变化。

// RequestManagerRetriever.java
// 根据传入的 Activity 获取 RequestManager
@NonNull
RequestManager get(@NonNull Activity activity) {// 判断是否在后台线程,若是则使用 Activity 的 ApplicationContext 获取 RequestManagerif (Util.isOnBackgroundThread()) { return get(activity.getApplicationContext());} else {// 检查 Activity 是否已销毁,若已销毁则抛出异常assertNotDestroyed(activity); // 获取 Activity 的 FragmentManagerFragmentManager fm = activity.getFragmentManager(); // 调用 supportFragmentGet 方法获取 RequestManagerreturn supportFragmentGet(activity, fm, null, isActivityVisible(activity)); }
}// 辅助方法,用于获取 RequestManager
@NonNull
private RequestManager supportFragmentGet(@NonNull Context context,@NonNull FragmentManager fm,@Nullable Fragment parentHint,boolean isParentVisible) {// 获取 SupportRequestManagerFragment 实例,若不存在则创建SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint); // 从 SupportRequestManagerFragment 中获取 RequestManagerRequestManager requestManager = current.getRequestManager(); if (requestManager == null) {// 获取 Glide 实例Glide glide = Glide.get(context); // 创建 RequestManager 实例requestManager =factory.build(glide, current.getLifecycle(), current.getRequestManagerTreeNode(), context); // 将创建好的 RequestManager 设置到 SupportRequestManagerFragment 中current.setRequestManager(requestManager); }return requestManager;
}

在 supportFragmentGet() 方法中,先通过 getSupportRequestManagerFragment() 方法获取隐藏的 SupportRequestManagerFragment。若该 Fragment 不存在,就创建一个新的并添加到 Activity 或 Fragment 中。SupportRequestManagerFragment 会监听 Activity 或 Fragment 的生命周期变化,并把这些变化传递给 RequestManager

3. SupportRequestManagerFragment 的生命周期监听

SupportRequestManagerFragment 是一个隐藏的 Fragment,它继承自 Fragment 并实现了 LifecycleOwner 接口。通过实现这个接口,它可以将自身的生命周期事件暴露给 RequestManager

// SupportRequestManagerFragment.java
public class SupportRequestManagerFragment extends Fragment {// 持有 ActivityFragmentLifecycle 实例,用于管理和分发生命周期事件private final ActivityFragmentLifecycle lifecycle; // 持有 RequestManager 实例,用于管理图片请求private RequestManager requestManager; public SupportRequestManagerFragment() {// 调用另一个构造方法,传入默认的 ActivityFragmentLifecycle 实例this(new ActivityFragmentLifecycle()); }@VisibleForTestingpublic SupportRequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {this.lifecycle = lifecycle;}@Overridepublic void onStart() {super.onStart();// 调用 ActivityFragmentLifecycle 的 onStart 方法,传递生命周期事件lifecycle.onStart(); }@Overridepublic void onStop() {super.onStop();// 调用 ActivityFragmentLifecycle 的 onStop 方法,传递生命周期事件lifecycle.onStop(); }@Overridepublic void onDestroy() {super.onDestroy();// 调用 ActivityFragmentLifecycle 的 onDestroy 方法,传递生命周期事件lifecycle.onDestroy(); }@NonNullpublic Lifecycle getLifecycle() {return lifecycle;}public void setRequestManager(@Nullable RequestManager requestManager) {this.requestManager = requestManager;}@Nullablepublic RequestManager getRequestManager() {return requestManager;}
}

在 SupportRequestManagerFragment 的 onStart()onStop() 和 onDestroy() 方法中,会调用 ActivityFragmentLifecycle 的相应方法,把生命周期事件传递给 ActivityFragmentLifecycle

4. ActivityFragmentLifecycle 的事件分发

ActivityFragmentLifecycle 实现了 Lifecycle 接口,负责管理和分发生命周期事件。当 SupportRequestManagerFragment 的生命周期发生变化时,ActivityFragmentLifecycle 会将这些变化通知给所有注册的 LifecycleListener

// ActivityFragmentLifecycle.java
class ActivityFragmentLifecycle implements Lifecycle {// 使用 Set 集合存储 LifecycleListener,使用 WeakHashMap 避免内存泄漏private final Set<LifecycleListener> lifecycleListeners =Collections.newSetFromMap(new WeakHashMap<LifecycleListener, Boolean>()); private boolean isStarted;private boolean isDestroyed;@Overridepublic void addListener(@NonNull LifecycleListener listener) {// 将 LifecycleListener 添加到集合中lifecycleListeners.add(listener); // 根据当前生命周期状态,调用 LifecycleListener 的相应方法if (isDestroyed) { listener.onDestroy();} else if (isStarted) {listener.onStart();} else {listener.onStop();}}@Overridepublic void removeListener(@NonNull LifecycleListener listener) {// 从集合中移除 LifecycleListenerlifecycleListeners.remove(listener); }void onStart() {isStarted = true;// 遍历 LifecycleListener 集合,调用每个 Listener 的 onStart 方法for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) { lifecycleListener.onStart();}}void onStop() {isStarted = false;// 遍历 LifecycleListener 集合,调用每个 Listener 的 onStop 方法for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) { lifecycleListener.onStop();}}void onDestroy() {isDestroyed = true;// 遍历 LifecycleListener 集合,调用每个 Listener 的 onDestroy 方法for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) { lifecycleListener.onDestroy();}}
}

RequestManager 实现了 LifecycleListener 接口,并注册到 ActivityFragmentLifecycle 中。当 ActivityFragmentLifecycle 接收到生命周期事件时,会调用 RequestManager 的相应方法,进而实现对图片请求的控制。

5. RequestManager 的生命周期响应

RequestManager 实现了 LifecycleListener 接口,会根据接收到的生命周期事件来控制图片请求的状态。

// RequestManager.java
public class RequestManager implements LifecycleListener, ModelTypes<RequestBuilder<Drawable>> {@Overridepublic void onStart() {// 调用 resumeRequests 方法,恢复所有暂停的图片请求resumeRequests(); }@Overridepublic void onStop() {// 调用 pauseRequests 方法,暂停所有正在运行的图片请求pauseRequests(); }@Overridepublic void onDestroy() {// 调用 clearRequests 方法,取消所有图片请求并释放资源clearRequests(); }public void resumeRequests() {isPaused = false;// 遍历 requests 集合,恢复未完成、未取消且未运行的请求for (Request request : Util.getSnapshot(requests)) { if (!request.isComplete() && !request.isCancelled() && !request.isRunning()) {request.begin();}}// 清空 pendingRequests 集合pendingRequests.clear(); }public void pauseRequests() {isPaused = true;// 遍历 requests 集合,暂停正在运行的请求,并将其添加到 pendingRequests 集合for (Request request : Util.getSnapshot(requests)) { if (request.isRunning()) {request.pause();pendingRequests.add(request);}}}public void clearRequests() {// 遍历 requests 集合,清除每个请求for (Request request : Util.getSnapshot(requests)) { request.clear();}// 清空 requests 和 pendingRequests 集合requests.clear(); pendingRequests.clear();}
}

当 RequestManager 接收到 onStart() 事件时,会调用 resumeRequests() 方法恢复所有暂停的图片请求;接收到 onStop() 事件时,调用 pauseRequests() 方法暂停所有正在运行的图片请求;接收到 onDestroy() 事件时,调用 clearRequests() 方法取消所有图片请求并释放资源。

相关文章:

Android学习总结之Glide篇(缓存和生命周期)

一、Glide缓存 1. 内存缓存 内存缓存主要包含活动资源缓存与 LRU 内存缓存这两个级别。 活动资源缓存&#xff08;Active Resources&#xff09; 作用&#xff1a;用于存放当前正在被显示的图片资源。当某张图片正展示在 ImageView 上时&#xff0c;它会被纳入活动资源缓存…...

Python 快速获取Excel工作表名称

文章目录 前言准备工作Python 获取Excel中所有工作表的名称Python 获取Excel中隐藏工作表的名称 前言 在数据分析与办公自动化领域&#xff0c;通过Python处理Excel文件已成为必备技能。通过获取工作表名称&#xff0c;我们可以&#xff1a; 快速了解文件结构自动化处理多工作…...

基于Docker的Flask项目部署完整指南

基于Docker的Flask项目部署完整指南 项目结构与文件说明 TextWeb/ ├── .dockerignore # Docker构建忽略配置 ├── Dockerfile # Docker镜像构建文件 ├── requirements.txt # Python依赖清单 └── WebServer/└── main.py # Fl…...

分布式定时任务(xxl-job)

简介 什么是XXL-JOB 详细的文档类容可以看下面这个链接进入readme xxl-job简介以及下载地址 XXL-JOB是一个分布式任务调度平台&#xff0c;其核心设计目标是开发迅速、学习简单、轻量级、易扩展 在Java Spring Cloud微服务架构中&#xff0c;使用独立的定时任务调度中心&…...

PostgreSQL使用LIKE右模糊没有走索引分析验证

建表&数据初始化可参考PostgreSQL 分区表——范围分区SQL实践 背景&#xff1a; 给t_common_work_order_log的handle_user_name新建索引后&#xff0c;使用LIKE右模糊匹配查询时&#xff0c;发现走的全表扫描 CREATE INDEX order_log_handle_user_name_index ON t_commo…...

Jenkins流水线管理工具

文章目录 前言&#xff1a; DevOps时代的自动化核心 —Jenkins一、Jenkins是什么&#xff1f;二、Linux安装Jenkinswar包方式安装依赖环境下载 Jenkins WAR 包启动 Jenkins 服务启动日志验证配置插件镜像源 docker镜像方式安装依赖环境拉取 Jenkins 镜像运行 Jenkins 容器获取初…...

2025年保安员证考试题库及答案

一、单选题 96、手指出血&#xff0c;为达到止血作用&#xff0c;应该压住&#xff08;&#xff09;。 A.出血手指的尖端 B.出血手指根部前后两侧 C.出血手指根部左右两侧 D.腕部的桡动脉、尺动脉 答案&#xff1a;C 97、下列选项中对干粉灭火器使用方法叙述错误的是&…...

观测云数据在Grafana展示的最佳实践

背景 在当今的数据驱动世界中&#xff0c;组织越来越依赖于实时数据来做出决策。数据可视化是理解和分析这些数据的关键工具&#xff0c;它帮助用户将复杂的数据集转换成直观的图表和仪表板&#xff0c;从而更容易识别趋势、模式和异常。Grafana&#xff0c;作为一个功能强大的…...

点云从入门到精通技术详解100篇-基于二次误差和高斯混合模型的点云配准算法

目录 知识储备 结合二次误差度量与高斯混合模型的点云配准 算法核心创新点: 关键参数说明: 性能优化建议: 前言 国内外研究现状 全局配准算法的国内外研究 局部配准算法的国内外研究 2 点云配准相关概念与方法 2.1 什么是点云配准 2.2 点云的获取及点云主要数据…...

shell命令一

&> /dev/null yum -y install vsftpd &> /dev/null&> /dev/null &>&#xff1a;将命令的**标准输出&#xff08;stdout&#xff09;和标准错误&#xff08;stderr&#xff09;**同时重定向。/dev/null&#xff1a;Linux中的“黑洞”设备&#xf…...

MySQL性能常用优化技巧总结

1. 索引优化 创建合适的索引 -- 为常用查询条件创建索引 ALTER TABLE users ADD INDEX idx_email (email); ALTER TABLE orders ADD INDEX idx_customer_date (customer_id, order_date);避免索引失效的情况 -- 避免在索引列上使用函数 SELECT * FROM users WHERE DATE(crea…...

在 Spring Boot 中实现 WebSockets

什么是 WebSockets&#xff1f; WebSockets 是一种基于 TCP 的全双工通信协议&#xff0c;允许客户端和服务器之间建立持久的双向连接&#xff0c;用于实时数据交换。相较于传统的 HTTP 请求-响应模型&#xff0c;WebSockets 提供了低延迟、高效率的通信方式&#xff0c;特别适…...

stone 3d v3.3.0版本发布,含时间线和连接器等新功能

1.新加了时间线&#xff08;timeline&#xff09;编辑器&#xff0c;可以类似blender一样给对象制作动画 2.新加了度量&#xff08;metrics&#xff09;系统&#xff0c;通过scene对象检测器中的useMetrics属性来启用或禁用&#xff0c;启用时所选物体将显示三维度量数据 新加了…...

Parasoft C++Test软件单元测试_对函数打桩的详细介绍

系列文章目录 Parasoft C++Test软件静态分析:操作指南(编码规范、质量度量)、常见问题及处理 Parasoft C++Test软件单元测试:操作指南、实例讲解、常见问题及处理 Parasoft C++Test软件集成测试:操作指南、实例讲解、常见问题及处理 进阶扩展:自动生成静态分析文档、自动…...

Safety Estimands与Efficacy Estimands的差异剖析

1. 研究目标差异 1.1 安全性估计目标 1.1.1 关注潜在风险 安全性估计目标着重于治疗可能引发的不良事件(AE)、严重不良事件(SAE)或实验室指标异常,如化疗药物导致中性粒细胞减少症的发生率,这些指标直接关联到患者治疗过程中的健康风险。 这些潜在风险的评估对于确保治…...

HTML 详解:从基础结构到语义标签

目录 一、HTML 是什么&#xff1f;二、HTML 的基本结构✅ 简要说明&#xff1a; 三、常见 HTML 标签讲解3.1 标题标签 <h1> ~ <h6>3.2 段落和换行3.3 超链接3.4 图像插入3.5 列表无序列表&#xff1a;有序列表&#xff1a; 3.6 表格结构 四、HTML 语义化标签详解五…...

联合索引`ABC`,使用`B=... AND C=... AND A=...`会走索引吗?

在MySQL中&#xff0c;联合索引ABC的查询使用B... AND C... AND A...时&#xff0c;是否使用索引取决于查询条件的顺序和优化器的处理。 一、索引使用原理 最左前缀原则 联合索引的底层存储和查询优化遵循最左前缀匹配原则&#xff0c;即查询条件必须从索引的最左侧列开始连续匹…...

HTML 模板技术与服务端渲染

HTML 模板技术与服务端渲染 引言 在现代前端开发生态中&#xff0c;HTML模板技术与服务端渲染(SSR)构成了连接前后端的重要桥梁。当单页应用(SPA)因其客户端渲染特性而面临首屏加载速度慢、白屏时间长和SEO不友好等问题时&#xff0c;服务端渲染技术提供了一种优雅的解决方案…...

MySQL的MVCC【学习笔记】

MVCC 事务的隔离级别分为四种&#xff0c;其中Read Committed和Repeatable Read隔离级别&#xff0c;部分实现就是通过MVCC&#xff08;Multi-Version Concurrency Control&#xff0c;多版本并发控制&#xff09; 版本链 版本链是通过undo日志实现的&#xff0c; 事务每次修改…...

linux安装单节点Elasticsearch(es),安装可视化工具kibana

真的&#xff0c;我安装个es和kibana&#xff0c;找了好多帖子&#xff0c;问了好几遍ai才安装成功&#xff0c;在这里记录一下&#xff0c;我相信&#xff0c;跟着我的步骤走&#xff0c;99%会成功&#xff1b; 为了让大家直观的看到安装过程&#xff0c;我把我服务器的es和ki…...

(Go Gin)上手Go Gin 基于Go语言开发的Web框架,本文介绍了各种路由的配置信息;包含各场景下请求参数的基本传入接收

1. 路由 gin 框架中采用的路优酷是基于httprouter做的 HttpRouter 是一个高性能的 HTTP 请求路由器&#xff0c;适用于 Go 语言。它的设计目标是提供高效的路由匹配和低内存占用&#xff0c;特别适合需要高性能和简单路由的应用场景。 主要特点 显式匹配&#xff1a;与其他路由…...

纯HTMLCSS静态网站——元神

《原神》主题网页介绍 以对该网页的详细介绍 网页整体结构 头部&#xff08;header&#xff09;&#xff1a;包含网站的 logo 和导航栏。logo 部分展示了 “原神” 字样&#xff0c;点击可返回首页。导航栏提供了多个页面链接&#xff0c;包括首页、音乐、视频、壁纸、世界、…...

嵌入式开发:基础知识介绍

一、嵌入式系统 1、介绍 以提高对象体系智能性、控制力和人机交互能力为目的&#xff0c;通过相互作用和内在指标评价的&#xff0c;嵌入到对象体系中的专用计算机系统。 2、分类 按其形态的差异&#xff0c;一般可将嵌入式系统分为&#xff1a;芯片级&#xff08;MCU、SoC&am…...

华为VRP系统简介配置TELNET远程登录!

1.华为 VRP 系统概述 1.1 什么是 VRP VRP&#xff08;Versatile Routing Platform 华为数通设备操作系统&#xff09;是华为公司数据通信产品的通用操作系统平台&#xff0c;从低端到核心的全系列路由器、以太网交换机、业务网关等产品的软件核心引擎。 1.2 VRP 的功能 统一…...

【高频考点精讲】CSS accent-color属性:如何快速自定义表单控件的颜色?

用CSS accent-color属性3分钟搞定表单控件换肤,原来这么简单! 前几天有个学员问我,checkbox和radio这些表单控件默认样式太丑了,有没有什么办法能快速改颜色?" 我一看这问题就乐了——这不正是CSS accent-color属性的拿手好戏吗?今天咱们就来好好聊聊这个被低估的C…...

【Git】连接github时的疑难杂症(DNS解析失败)

大家好&#xff0c;我是jstart千语。最近在将项目推送到github的时候&#xff0c;突然github就拒绝访问了&#xff0c;即使挂了VPN&#xff0c;网页也进不去&#xff0c;通过git也不能把代码推送上去。 即使后面看别人的一些解决方案&#xff0c;比如取消代理啊、更换ssh的方式…...

成熟的前端vue vite websocket,Django后端实现方案包含主动断开websocket连接的实现

可参考实现方式点击进入查看 具体实现方案如下所示&#xff1a; import { useWebsocketMsessageStore } from /stores/websocketMsessageStore.js import {ElMessage} from "element-plus"; import {useUserStore} from "/stores/userStore.js"; // impo…...

广州 3D 展厅开启企业展示新时代​

为了突破传统展厅的局限&#xff0c;满足企业日益增长的展示需求&#xff0c;3D 展厅应运而生。3D 展厅是利用虚拟现实&#xff08;VR&#xff09;、增强现实&#xff08;AR&#xff09;和三维建模等先进技术&#xff0c;构建出的一个高度逼真的数字化展示空间 。它打破了传统展…...

【Django】新增字段后兼容旧接口 This field is required

背景 我在Django模型里新增了两个字段后&#xff0c;旧的接口由于没有同时新增这两个字段的处理&#xff0c;因此旧的接口就报&#xff1a; This field is required 解决 把序列化时的 required 的字段设置为False即可 class ServiceSerializer(DynamicFieldsModelSerializ…...

基于AIGC的3D场景生成实战:从文本描述到虚拟世界构建

一、3D AIGC技术解析 1.1 技术挑战与突破 挑战维度 传统方案局限 AIGC创新方案 建模效率 人工建模耗时数天 文本到3D秒级生成 细节丰富度 重复使用素材库 无限风格化生成 物理合理性 手动调整物理参数 自动符合物理规律 多平台适配 需手动优化模型 自适应LOD生成 1.2 主流技术路…...

手写Java线程池与定时器:彻底掌握多线程任务调度

​ 目录 一、线程池 1.1、什么是线程池 1.2、Java标准库中的线程池 1.3、ThreadPoolExecutor的七大参数 1.4、模拟实现线程池 1.4.1、submit () 1.4.2、构造方法 1.4.3、运行结果 二、定时器​ 2.1、标准库中的定时器 2.2、模拟实现定时器 2.2.1、MyTimerTask类 2…...

【科研绘图系列】R语言绘制区间点图(dot plot)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载导入数据数据预处理画图1画图2输出图片系统信息介绍 【科研绘图系列】R语言绘制区间点图(dot plot) 加载R包 library(tidyverse) library(ggtext) library(r…...

【Agent实战】从0到1开发一个Python 解释器 MCP SSE Server

写在前面 想象一个场景:LLM Agent(如 AutoGPT、MetaGPT 或我们自己构建的 Agent)在规划任务后,决定需要运行一段 Python 代码来处理数据或调用某个 API。它不能直接在自己的环境中执行(通常不具备这个能力,也不安全),而是需要将这段代码发送给一个专门的外部服务来执行…...

C语言大写转小写2.0

一、阐述关系 上一次的题目是大写转小写,这一次代码不一样,运行的结果也不一样,这次的代码在此基础之上改动了一下,虽然看起来相似,但实际上运行结果不一样 二、题目展示 下面代码中,运行的结果是多少? 三、分析过程 首先,进入main函数,先声明了一个字符型数组是"012…...

pnpm常见报错解决办法

PS D:\code\gitlab\manus-web> pnpm add -D types/framer-motion --save-exact --config.strict-peer-depsfalse Debugger attached.  WARN  deprecated eslint8.57.1: This version is no longer supported. Please see https://eslint.org/version-support for other op…...

【Linux网络】:套接字之UDP

一、UDP和TCP协议 TCP &#xff08;Transmission Control Protocol 传输控制协议&#xff09;的特点&#xff1a; 传输层协议有连接&#xff08;在正式通信前要先建立连接&#xff09;可靠传输&#xff08;在内部帮我们做可靠传输工作&#xff09;面向字节流 UDP &#xff08;U…...

量子威胁下的安全革命:后量子密码学技术路线与迁移挑战全解析

引言 量子计算技术的快速发展正在重塑现代密码学的安全版图。随着Shor算法对传统公钥密码体系的根本性威胁[1]&#xff0c;全球范围内后量子密码学&#xff08;Post-Quantum Cryptography, PQC&#xff09;的研究与标准化进程已进入关键阶段。 本文基于权威文献分析&#xff0c…...

多模态大语言模型(MLLM)- kimi-vl technical report论文阅读

前言 kimi-vl是月之暗面团队于2025年4月10日发布的多模态大模型。 代码链接&#xff1a;https://github.com/MoonshotAI/Kimi-VL 背景 随着人工智能技术的快速发展&#xff0c;人们对AI助手的需求已从单一文本交互转向多模态理解。新一代多模态模型如GPT-4o和Gemini虽展现…...

ai聊天流式响应,阻塞式和流式响应 nginx遇到的坑

问题 现在做ai的流式请求&#xff0c;在开发环境使用代理访问接口&#xff0c;显示是正常的。上到正式环境&#xff0c;代理通过nginx配置可以访问到流式接口。在本地测试postman请求流式接口&#xff0c;返回的东西是流式返回&#xff0c; 在正式环境里面使用postman请求流式…...

Linux安全模块:SELinux与AppArmor深度解析

引言 在Linux安全领域&#xff0c;SELinux和AppArmor就像两位忠诚的"系统保镖"&#x1f482;&#xff0c;为你的服务器提供强制访问控制(MAC)保护&#xff01;本文将深入解析这两大安全模块的工作原理、配置方法和实战技巧。无论你是要加固Web服务器&#xff0c;还是…...

FlinkJobmanager深度解析

1. JobManager 概述 Flink 是一个分布式流处理框架&#xff0c;其核心组件包括 JobManager、TaskManager 和客户端&#xff08;如 CLI 或 Web UI&#xff09;。JobManager 是 Flink 集群的“大脑”&#xff0c;负责协调作业的整个生命周期&#xff0c;包括作业调度、资源管理、…...

FlinkSql入门与实践

一、为什么需要 Flink SQL&#xff1f; 传统 SQL 是面向静态数据的查询语言&#xff0c;而现代实时业务要求对动态数据流进行即时分析。Flink SQL 应运而生&#xff0c;它让开发者无需编写复杂的状态管理代码&#xff0c;就能实现实时ETL、复杂事件处理&#xff08;CEP&#x…...

【物联网】基于LORA组网的远程环境监测系统设计(ThingsCloud云平台版)

演示视频: 基于LORA组网的远程环境监测系统设计(ThingsCloud云平台版) 前言:本设计是基于ThingsCloud云平台版,还有另外一个版本是基于机智云平台版本,两个设计只是云平台和手机APP的区别,其他功能都一样。如下链接: 【物联网】基于LORA组网的远程环境监测系统设计(机…...

C++中指针Ptr(一级指针、二级指针)的基本使用详解(1)

C 中的指针是非常强大的工具&#xff0c;理解一级指针、二级指针以及它们与数组的关系&#xff0c;对于写出高效且安全的程序非常重要。下面我将从基础讲起&#xff0c;详细解释 一级指针、二级指针 的使用&#xff0c;注意事项&#xff0c;以及它们和数组之间的联系与区别&…...

科技赋能建筑新未来:中建海龙模块化建筑产品入选中国建筑首批产业化推广产品

在建筑工业化浪潮中&#xff0c;中国建筑国际集团旗下中建海龙科技有限公司&#xff08;以下简称“中建海龙”&#xff09;致力以科技创新赋能传统建造转型升级&#xff0c;大力发展新质生产力&#xff0c;促进科技成果在建筑产业体系化、规模化应用&#xff0c;面向“产品化、…...

示例:Spring JDBC 声明式事务(xml配置形式)

声明式事务是指在不修改源代码的情况下通过配置applicationContext.xml自动实现事务控制&#xff0c;其本质是AOP环绕通知。它的触发时机为&#xff1a;1、当目标方法执行成功时自动提交事务&#xff0c;2、当目标方法抛出运行时异常时&#xff0c;自动事务回滚 核心步骤示例&a…...

java多线程(7.0)

目录 ​编辑 定时器 定时器的使用 三.定时器的实现 MyTimer 3.1 分析思路 1. 创建执行任务的类。 2. 管理任务 3. 执行任务 3.2 线程安全问题 定时器 定时器是软件开发中的一个重要组件. 类似于一个 "闹钟". 达到一个设定的时间之后, 就执行某个指定好的…...

sgpt在kali应用

Kali Linux 下 sgpt 渗透测试相关案例 1. 扫描目标主机存活 sgpt -s "使用 nmap 扫描 192.168.1.100 是否存活"示例命令&#xff1a; nmap -sn 192.168.1.1002. 扫描目标主机开放端口和服务 sgpt -s "使用 nmap 扫描 192.168.1.100 常见端口和服务"示例…...

小白电路设计-设计11-恒功率充电电路设计

介绍 作为电子信息工程的我&#xff0c;电路学习是一定要学习的&#xff0c;可惜目前作为EMC测试工程师&#xff0c;无法兼顾太多&#xff0c;索性不如直接将所学的知识进行运用&#xff0c;并且也可以作为契机&#xff0c;进行我本人的个人提升。祝大家与我一起进行提升。1.本…...

express的模板handlebars用app.engine()创建配置和用exphbs.create()的区别

在使用 express-handlebars 时&#xff0c;app.engine 和 exphbs.create 都可以用来配置 Handlebars 模板引擎&#xff0c;但它们的使用方式和功能有一些区别。以下是详细的对比和说明 app.engine 方法 app.engine 是 Express 提供的方法&#xff0c;用于注册一个新的模板引擎…...