移动应用开发:自定义 View 处理大量数据的性能与交互优化方案
实现 1 万条数据下流畅滑动与灵敏交互的完美平衡。
一、数据渲染优化:从 1 万条到丝滑体验
(一)视图复用机制
视图复用是提升大量数据渲染性能的关键策略。以一个简单的自定义列表视图为例,我们可以构建如下的复用池管理机制:
private final LinkedList<ViewHolder> viewPool = new LinkedList<>();
private final WeakHashMap<Integer, ViewHolder> cacheMap = new WeakHashMap<>();private ViewHolder obtainViewHolder(int position) {ViewHolder holder = cacheMap.get(position);if (holder == null) {holder = viewPool.poll();if (holder == null) {holder = new ViewHolder(inflateItem());}}return holder;
}private void recycleViewHolder(int position, ViewHolder holder) {cacheMap.put(position, holder);viewPool.offer(holder);
}
这里,viewPool
作为一个可复用视图持有者的队列,cacheMap
则通过弱引用缓存特定位置的视图持有者。在获取视图持有者时,优先从缓存中查找,如果未找到则尝试从复用池中取出,若复用池为空则创建新的视图持有者。当视图不再显示时,将其回收至复用池和缓存中,以便后续复用。这种机制大大减少了视图创建的开销,显著提升渲染效率。
(二)按需绘制策略
按需绘制能有效避免绘制不可见区域,从而提升性能。在自定义 View 的 onDraw
方法中,我们可以这样实现:
@Override
protected void onDraw(Canvas canvas) {int start = (int) Math.floor(scrollY / itemHeight);int end = (int) Math.ceil((scrollY + getHeight()) / itemHeight);// 绘制可见区域for (int i = start; i <= end; i++) {drawItem(canvas, i);}// 硬件加速缓存if (Build.VERSION.SDK_INT >= 23) {setLayerType(LAYER_TYPE_HARDWARE, null);}
}
通过计算当前滚动位置 scrollY
和视图高度 getHeight()
,确定可见区域的起始和结束索引 start
和 end
。仅对可见区域内的列表项进行绘制,极大减少了不必要的绘制操作。同时,对于 API 23 及以上的系统,开启硬件加速,进一步提升绘制性能。
(三)内存管理优化
良好的内存管理是确保应用长期稳定运行的关键。在自定义 View 与窗口分离时,应及时释放相关资源:
@Override
protected void onDetachedFromWindow() {super.onDetachedFromWindow();// 释放资源if (cacheBitmap != null && !cacheBitmap.isRecycled()) {cacheBitmap.recycle();cacheBitmap = null;}viewPool.clear();cacheMap.clear();
}
这里,当自定义 View 从窗口分离时,检查并回收可能存在的缓存位图 cacheBitmap
,同时清空视图复用池 viewPool
和缓存映射 cacheMap
,避免内存泄漏,保证内存的高效利用。
二、事件分发优化:从触摸到响应的精准控制
(一)滑动冲突解决方案
在复杂的视图层级中,滑动冲突时有发生。以一个包含横向和纵向滑动的自定义 ViewGroup 为例,我们可以通过如下方式处理:
public class CustomViewGroup extends LinearLayout {private boolean isIntercept = false;private float startX;private float startY;@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:isIntercept = false;startX = ev.getX();startY = ev.getY();break;case MotionEvent.ACTION_MOVE:// 根据滑动距离判断是否拦截float dx = ev.getX() - startX;float dy = ev.getY() - startY;isIntercept = Math.abs(dx) > Math.abs(dy);break;}return isIntercept;}
}
在 onInterceptTouchEvent
方法中,当触摸事件为 ACTION_DOWN
时,初始化起始坐标并重置拦截标志。在 ACTION_MOVE
事件中,通过比较横向和纵向的滑动距离 dx
和 dy
,判断是否拦截事件。如果横向滑动距离大于纵向,则拦截事件,交由当前 ViewGroup 处理,避免与子 View 的滑动冲突。
(二)惯性滚动实现
为了实现流畅的惯性滚动效果,我们可以借助 Scroller
和 VelocityTracker
:
private Scroller scroller;
private VelocityTracker velocityTracker;@Override
public boolean onTouchEvent(MotionEvent event) {if (velocityTracker == null) {velocityTracker = VelocityTracker.obtain();}velocityTracker.addMovement(event);if (event.getAction() == MotionEvent.ACTION_UP) {velocityTracker.computeCurrentVelocity(1000);int velocityY = (int) velocityTracker.getYVelocity();scroller.fling(0, getScrollY(), 0, -velocityY, 0, 0, 0, maxScrollY);invalidate();velocityTracker.recycle();velocityTracker = null;}return true;
}@Override
public void computeScroll() {if (scroller.computeScrollOffset()) {scrollTo(scroller.getCurrX(), scroller.getCurrY());invalidate();}
}
在 onTouchEvent
方法中,当手指抬起(ACTION_UP
)时,计算当前触摸速度 velocityY
,并使用 scroller.fling
方法启动惯性滚动动画。在 computeScroll
方法中,不断更新滚动位置,直到滚动动画结束,从而实现自然流畅的惯性滚动效果。
三、综合实践:高性能列表的完整实现
(一)适配器设计
适配器在数据与视图之间起到桥梁作用。一个通用的适配器设计如下:
public abstract class DataAdapter<T> {public abstract int getItemCount();public abstract T getItem(int position);public abstract int getItemHeight(int position);public abstract void bindViewHolder(ViewHolder holder, T item);
}
通过抽象方法,强制实现类提供数据项数量、获取指定位置的数据项、获取数据项高度以及绑定数据到视图持有者的功能,确保数据与视图的高效适配。
(二)自定义 View 整合
将上述技术整合到一个自定义的高性能列表视图 HighPerfListView
中:
public class HighPerfListView extends ViewGroup {private DataAdapter<?> adapter;private int itemHeight = 150;private int scrollY;@Overrideprotected void onDraw(Canvas canvas) {int visibleStart = (int) Math.floor(scrollY / itemHeight);int visibleEnd = (int) Math.ceil((scrollY + getHeight()) / itemHeight);for (int i = visibleStart; i <= visibleEnd; i++) {if (i >= adapter.getItemCount()) break;drawItem(canvas, i);}}private void drawItem(Canvas canvas, int position) {ViewHolder holder = obtainViewHolder(position);adapter.bindViewHolder(holder, adapter.getItem(position));holder.itemView.layout(0, position*itemHeight - scrollY, getWidth(), (position+1)*itemHeight - scrollY);holder.itemView.draw(canvas);recycleViewHolder(position, holder);}private ViewHolder obtainViewHolder(int position) {// 复用池和缓存获取逻辑}private void recycleViewHolder(int position, ViewHolder holder) {// 复用池和缓存回收逻辑}
}
在 onDraw
方法中,根据滚动位置计算可见区域并绘制相应的数据项。drawItem
方法负责获取视图持有者、绑定数据、布局并绘制视图,最后回收视图持有者,实现高效的数据渲染与视图管理。
(三)性能监控
为了评估优化效果,我们可以进行性能监控,例如帧率统计:
private static final String TAG = "HighPerfListView";
private long startTime = System.currentTimeMillis();
private int frameCount = 0;@Override
protected void onDraw(Canvas canvas) {super.onDraw(canvas);frameCount++;if (System.currentTimeMillis() - startTime >= 1000) {Log.d(TAG, "FPS: " + frameCount);frameCount = 0;startTime = System.currentTimeMillis();}
}
通过在每次 onDraw
时统计帧数,每秒输出一次帧率,直观反映视图的渲染性能,便于进一步优化调整。
四、优化总结与建议
通过上述优化策略,我们在数据渲染、事件处理和内存管理等方面取得了显著收益:
优化维度 | 关键技术 | 收益 |
---|---|---|
数据渲染 | 视图复用 / 按需绘制 / 硬件加速 | 内存降低 50%,帧率提升 30% |
事件处理 | 精准拦截 / 手势检测 / 惯性滚动 | 响应延迟减少 40% |
内存管理 | 弱引用缓存 / 资源及时释放 | GC 频率降低 60% |
同时,我们给出以下最佳实践建议:
- 优先使用 RecyclerView 处理列表:RecyclerView 已经内置了高效的视图复用和布局管理机制,对于常规列表场景,优先选择它能大大减少开发成本和提升性能。
- 滑动过程中避免复杂计算:滑动过程中应尽量避免复杂的计算操作,以免阻塞主线程。可以使用
postOnAnimation
方法将复杂计算延迟到下一帧动画时处理。 - 结合 Android Profiler 监控内存与帧率:Android Profiler 提供了强大的性能分析工具,通过它可以实时监控内存使用情况和帧率变化,精准定位性能瓶颈。
- 对不可见区域视图设置 setVisibility (GONE) 而非隐藏:将不可见区域的视图设置为
GONE
可以避免不必要的绘制和布局计算,进一步提升性能。 - 使用 ViewStub 延迟加载非关键视图:对于一些非关键的视图,可以使用 ViewStub 进行延迟加载,在需要时才加载并初始化,减少应用启动和初始渲染的时间。
五、高频面试真题讲解
在 Android 开发面试中,自定义 View 相关知识是大厂重点考察内容。以下结合往届大厂面试真题,为你详细解析常见考点:
(一)面试题目 1:解释自定义 View 的基本概念及其在 Android 开发中的重要性
大厂真题示例:在美团面试中,曾要求候选人举例说明自定义 View 在实际项目中的应用场景及其优势。
解答:自定义 View 是 Android 开发中允许开发者根据应用特定需求创建全新视图组件的核心概念。系统提供的标准 View 无法满足所有界面设计和交互需求,因此自定义 View 成为打造差异化用户体验的关键。
其重要性体现在:
- 灵活性与创新性:开发者可通过继承
View
或ViewGroup
子类,重写onMeasure
、onLayout
、onDraw
等方法,实现个性化的视图逻辑。例如在支付宝 APP 中,账单详情页的环形统计图就通过自定义 View 实现精准的数据可视化。 - 业务场景适配:在金融类应用中,复杂的 K 线图表;游戏开发中的动态游戏界面;音乐类应用中带有波形动画的进度条,这些特殊功能都依赖自定义 View 实现。以网易云音乐为例,其播放界面的唱片转动效果就是通过自定义 View 完成的动画交互。
(二)面试题目 2:详细解释 View 的测量过程以及 onMeasure
方法的作用
大厂真题示例:字节跳动面试中曾要求候选人手写 onMeasure
方法,实现一个固定宽高比的自定义图片 View。
解答:View 的测量过程是确定 View 大小的核心流程,具体如下:
- 触发机制:当 View 被添加到视图层级时,其父 View 调用
measure
方法触发子 View 的测量。 - MeasureSpec:父 View 向子 View 传递
MeasureSpec
,它由测量模式和测量大小两部分组成:EXACTLY
:父 View 确定子 View 的具体大小,如设置android:layout_width="100dp"
时;AT_MOST
:子 View 大小不能超过父 View 指定的最大尺寸,常见于wrap_content
场景;UNSPECIFIED
:父 View 不对子 View 大小做限制,一般用于系统内部测量。
onMeasure
方法:开发者通过重写该方法控制 View 的宽高。例如实现一个固定宽高比为2:1
的自定义图片 View:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int widthMode = MeasureSpec.getMode(widthMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);if (widthMode == MeasureSpec.EXACTLY && heightMode == MeasureSpec.AT_MOST) {heightSize = widthSize / 2;} else if (heightMode == MeasureSpec.EXACTLY && widthMode == MeasureSpec.AT_MOST) {widthSize = heightSize * 2;}setMeasuredDimension(widthSize, heightSize);
}
最后通过 setMeasuredDimension
方法设置 View 的测量宽高。
(三)面试题目 3:详细解释自定义 View 的绘制流程
大厂真题示例:腾讯面试中要求候选人阐述自定义 View 从创建到显示在屏幕上的完整流程。
解答:自定义 View 的绘制流程分为三个阶段:
- 测量阶段:通过
onMeasure
方法确定 View 大小,根据父 View 传递的MeasureSpec
计算合适的宽高,并调用setMeasuredDimension
设置。 - 布局阶段:在
onLayout
方法中,确定 View 及其子 View 在父 View 中的位置。对于ViewGroup
子类,需要遍历子 View 并调用child.layout()
设置其坐标。例如实现一个水平排列子 View 的自定义ViewGroup
:
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {int childCount = getChildCount();int left = 0;for (int i = 0; i < childCount; i++) {View child = getChildAt(i);int width = child.getMeasuredWidth();int height = child.getMeasuredHeight();child.layout(left, 0, left + width, height);left += width;}
}
- 绘制阶段:在
onDraw
方法中,使用Canvas
对象完成实际绘制,如绘制图形、文本、图片等。如需更新视图,可调用invalidate
方法触发重绘,系统会再次执行onDraw
。
(四)面试题目 4:在自定义 View 中,如何使用 onInterceptTouchEvent
方法进行事件拦截?
大厂真题示例:阿里巴巴面试中要求候选人设计一个可嵌套滑动的自定义 ViewGroup
,并解决滑动冲突问题。
解答:onInterceptTouchEvent
用于决定是否拦截触摸事件,具体流程如下:
- 事件传递顺序:触摸事件发生时,系统先调用 View 的
onInterceptTouchEvent
方法。 - 拦截逻辑:在方法中根据事件类型和位置判断是否拦截。例如在一个包含横向滑动子 View 的
ViewGroup
中:
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:startX = ev.getX();startY = ev.getY();break;case MotionEvent.ACTION_MOVE:float dx = ev.getX() - startX;float dy = ev.getY() - startY;// 横向滑动距离超过阈值时拦截if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > SLIDE_THRESHOLD) {return true;}break;}return false;
}
当返回 true
时,后续事件(如 ACTION_UP
)将直接交给当前 ViewGroup
的 onTouchEvent
处理,不再传递给子 View。
3. 子 View 反拦截:子 View 可通过 requestDisallowInterceptTouchEvent
方法阻止父 View 拦截后续事件,实现嵌套滑动场景下的灵活控制。
(五)面试题目 5:解释自定义 View 中事件的消费流程
大厂真题示例:华为面试中要求候选人画出 Android 事件分发与消费的流程图,并说明关键方法的作用。
解答:自定义 View 事件消费流程以 onTouchEvent
为核心,具体如下:
- 事件传递:触摸事件封装为
MotionEvent
对象,从父 View 逐层传递至子 View。 onTouchEvent
处理:View 的onTouchEvent
方法根据事件类型(ACTION_DOWN
、ACTION_MOVE
、ACTION_UP
等)处理逻辑。若返回true
,表示事件被消费,不再传递给父 View。例如自定义按钮点击事件:
@Override
public boolean onTouchEvent(MotionEvent event) {if (event.getAction() == MotionEvent.ACTION_DOWN) {// 按下时的逻辑} else if (event.getAction() == MotionEvent.ACTION_UP) {// 抬起时执行点击逻辑performClick();return true;}return super.onTouchEvent(event);
}
onInterceptTouchEvent
影响:若父 View 的onInterceptTouchEvent
返回true
,事件将被拦截并由父 View 的onTouchEvent
处理。- 反拦截机制:子 View 可调用
requestDisallowInterceptTouchEvent
改变事件传递路径,实现复杂交互场景下的精准控制。
相关文章:
移动应用开发:自定义 View 处理大量数据的性能与交互优化方案
实现 1 万条数据下流畅滑动与灵敏交互的完美平衡。 一、数据渲染优化:从 1 万条到丝滑体验 (一)视图复用机制 视图复用是提升大量数据渲染性能的关键策略。以一个简单的自定义列表视图为例,我们可以构建如下的复用池管理机制&a…...

绘制拖拽html
<!DOCTYPE html> <html lang"zh-CN"> <head> <meta charset"UTF-8" /> <meta name"viewport" content"widthdevice-width, initial-scale1" /> <title>拖拽绘制矩形框 - 可移动可调整大小</ti…...
C++结构体介绍
结构体的定义 在C中,结构体(struct)是一种用户定义的数据类型,允许将不同类型的数据组合在一起。结构体的定义使用struct关键字,后跟结构体名称和一对花括号{},花括号内包含成员变量的声明。 struct Pers…...

ggplot2 | GO barplot with gene list
1. 效果图 2. 代码 数据是GO的输出结果,本文使用的是 metascape 输出的excel挑选的若干行。 # 1. 读取数据 datread.csv("E:\\research\\scPolyA-seq2\\GO-APA-Timepoint\\test.csv", sep"\t") head(dat)# 2. 选择所需要的列 dat.usedat[, c(…...
PostgreSQL 的 pg_advisory_lock 函数
PostgreSQL 的 pg_advisory_lock 函数 pg_advisory_lock 是 PostgreSQL 提供的一种应用级锁机制,它不锁定具体的数据库对象(如表或行),而是通过数字键值来协调应用间的并发控制。 锁的基本概念 PostgreSQL 提供两种咨询锁(advi…...
docker 镜像的导出和导入(导出完整镜像和导出容器快照)
一、导出原始镜像 1. 使用 docker save 导出完整镜像 适用场景:保留镜像的所有层、元数据、标签和历史记录,适合迁移或备份完整镜像环境。 操作命令 docker save -o <导出文件名.tar> <镜像名:标签>示例:docker save -o milvu…...

系统思考:短期困境与长期收益
最近在项目中,一直有学员会提到一个议题,如何平衡当前困境和长期收益? 我的思考是在商业和人生的路上,我们常常听到“鱼和熊掌不可兼得”的说法,似乎短期利益和长期目标注定是对立的。但事实上,鱼与熊掌是…...
4.2【LLaMA-Factory实战】金融财报分析系统:从数据到部署的全流程实践
【LLaMA-Factory实战】金融财报分析系统:从数据到部署的全流程实践 一、引言 在金融领域,财报分析是投资决策的核心环节。传统分析方法面临信息提取效率低、风险识别不全面等挑战。本文基于LLaMA-Factory框架,详细介绍如何构建一个专业的金…...

Cjson格式解析与接入AI大模型
JSON格式的解析与构造 基本概念 JSON是JavaScript Object Notation的简称,中文含义为“JavaScript 对象表示法”,它是一种数据交换的文本格式,而不是一种编程语言。 JSON 是一种轻量级的数据交换格式,采用完全独立于编程语言的…...

基于英特尔 RealSense D455 结构光相机实现裂缝尺寸以及深度测量
目录 一,相机参数规格 二,结合YOLO实例分割实现裂缝尺寸以及深度测量 2.1 应用场景 2.2 实现流程 2.3 效果展示 2.4 精度验证 2.5 实物裂缝尺寸以及深度测量效果展示 一,相机参数规格 英特尔 RealSense D455 是英特尔 RealSense D400 系…...

Nacos源码—7.Nacos升级gRPC分析四
大纲 5.服务变动时如何通知订阅的客户端 6.微服务实例信息如何同步集群节点 6.微服务实例信息如何同步集群节点 (1)服务端处理服务注册时会发布一个ClientChangedEvent事件 (2)ClientChangedEvent事件的处理源码 (3)集群节点处理数据同步请求的源码 (1)服务端处理服务注册…...

TIME - MoE 模型代码 3.2——Time-MoE-main/time_moe/datasets/time_moe_dataset.py
源码:GitHub - Time-MoE/Time-MoE: [ICLR 2025 Spotlight] Official implementation of "Time-MoE: Billion-Scale Time Series Foundation Models with Mixture of Experts" 这段代码定义了一个用于时间序列数据处理的 TimeMoEDataset 类,支…...

【某OTA网站】phantom-token 1004
新版1004 phantom-token 请求头中包含phantom-token 定位到 window.signature 熟悉的vmp 和xhs一样 最新环境检测点 最新检测 canvas 下的 toDataURL方法较严 过程中 会用setAttribute给canvas 设置width height 从而使toDataURL返回不同的值 如果写死toDataURL的返回值…...

OrangePi Zero 3学习笔记(Android篇)2 - 第一个C程序
目录 1. 创建项目文件夹 2. 创建c/cpp文件 3. 创建Android.mk/Android.bp文件 3.1 Android.mk 3.2 Android.bp 4. 编译 5. adb push 6. 打包到image中 在AOSP里面添加一个C或C程序,这个程序在Android中需要通过shell的方式运行。 1. 创建项目文件夹 首先需…...

DeepResearch深度搜索实现方法调研
DeepResearch深度搜索实现方法调研 Deep Research 有三个核心能力 能力一:自主规划解决问题的搜索路径(生成子问题,queries,检索)能力二:在探索路径时动态调整搜索方向(刘亦菲最好的一部电影是…...
使用大语言模型进行机器人规划(Robot planning with LLMs)
李升伟 编译 长期规划在机器人学领域可以从经典控制方法与大型语言模型在现实世界知识能力的结合中获益。 在20世纪80年代,机器人学和人工智能(AI)领域的专家提出了莫雷奇悖论,观察到人类看似简单的涉及移动和感知的任务&#x…...

【论文阅读】基于客户端数据子空间主角度的聚类联邦学习分布相似性高效识别
Efficient distribution similarity identification in clustered federated learning via principal angles between client data subspaces -- 基于客户端数据子空间主角度的聚类联邦学习分布相似性高效识别 论文来源TLDR背景与问题两个子空间之间的主角(Principa…...

Elasticsearch知识汇总之ElasticSearch部署
五 ElasticSearch部署 部署Elasticsearch,可以在任何 Linux、MacOS 或 Windows 机器上运行 Elasticsearch。在Docker 容器 中运行 Elasticsearch 。使用Elastic Cloud on Kubernetes 设置和管理 Elasticsearch、Kibana、Elastic Agent 以及 Kubernetes 上的 Elasti…...

ROBOVERSE:面向可扩展和可泛化机器人学习的统一平台、数据集和基准
25年4月来自UC Berkeley、北大、USC、UMich、UIUC、Stanford、CMU、UCLA 和 北京通用 AI 研究院(BIGAI)的论文“ROBOVERSE: Towards a Unified Platform, Dataset and Benchmark for Scalable and Generalizable Robot Learning”。 数据扩展和标准化评…...
LVGL的核心:lv_timer_handler
文章目录 🧠 一句话总结 LVGL 的运行核心:🔁 1. while(1) 主循环中的 lv_task_handler()⏱️ 2. lv_timer_handler() 定时器调度核心✅ 并发控制✅ 关键行为流程:🌀 任务执行逻辑:🧮 计算下一次…...

(41)VTK C++开发示例 ---qt使用vtk最小示例
文章目录 1. 概述2. CMake链接VTK3. main.cpp文件4. 演示效果 更多精彩内容👉内容导航 👈👉VTK开发 👈 1. 概述 本文演示了在Qt中使用VTK的最小示例程序,使用VTK创建显示一个锥体; 采用Cmake作为构建工具&a…...
⭐️⭐️⭐️【课时1:大模型是什么?】学习总结 ⭐️⭐️⭐️ for《大模型Clouder认证:基于百炼平台构建智能体应用》认证
一、学习目标 概要 通过学习《课时1:大模型是什么?》,全面了解大模型的基础概念、核心特点、发展脉络及阿里云在大模型领域的布局,为后续基于百炼平台构建智能体应用的实践操作打下坚实的理论基础。 具体目标列表 理解人工智能到大模型的演变逻辑,明确大模型在AI发展历…...

OS7.【Linux】基本指令入门(6)
目录 1.zip和unzip 配置指令 使用 两个名词:打包和压缩 打包 压缩 Linux下的操作演示 压缩和解压缩文件 压缩和解压缩目录 -d选项 2.tar Linux下的打包和压缩方案简介 czf选项 xzf选项 -C选项 tzf选项 3.bc 4.uname 不带选项的uname -a选项 -r选项 -v选项…...

国标GB28181视频平台EasyCVR安防系统部署知识:如何解决异地监控集中管理和组网问题
在企业、连锁机构及园区管理等场景中,异地监控集中管控与快速组网需求日益迫切。弱电项目人员和企业管理者亟需整合分散监控资源,实现跨区域统一管理与实时查看。 一、解决方案 案例一:运营商专线方案 利用运营商专线,连接各分…...

O2O上门服务如何颠覆传统足浴行业?真实案例分析
在湖南经营传统足浴店的张总最近遇到了件让他哭笑不得的事。原本他的门店生意还算稳定,虽然这两年行情不好,但靠着老顾客还能勉强维持。可谁想到,一次好心帮忙,竟让他发现了行业的新天地。 几年前,张总的一位做砂石生意…...

金仓数据库永久增量备份技术原理与操作
先用一张图说明一下常见的备份方式 为什么需要永久增量备份 传统的数据库备份方案通常是间隔7天对数据库做一次全量备份(完整备份),每天会基于全量备份做一次增量备份,如此循环,这种备份方案在全备数据量过大场景下…...

19、HashTable(哈希)、位图的实现和布隆过滤器的介绍
一、了解哈希【散列表】 1、哈希的结构 在STL中,HashTable是一个重要的底层数据结构, 无序关联容器包括unordered_set, unordered_map内部都是基于哈希表实现 哈希表又称散列表,一种以「key-value」形式存储数据的数据结构。哈希函数:负责将…...
函数级重构:如何写出高可读性的方法?
1. 引言:为什么方法级别的重构如此重要? 在软件开发中,方法(函数)是程序逻辑的基本单元。一个高质量的方法不仅决定了程序是否能正常运行,更直接影响到: 代码的可读性:能否让其他开发者快速理解可维护性:未来修改是否容易出错可测试性:是否便于编写单元测试协作效率…...

mysql中int(1) 和 int(10) 有什么区别?
困惑 最近遇到个问题,有个表的要加个user_id字段,user_id字段可能很大,于是我提mysql工单alter table xxx ADD user_id int(1)。领导看到我的sql工单,于是说:这int(1)怕是不够用吧,接下来是一通解…...

FreeRTOS如何实现100%的硬实时性?
实时系统在嵌入式应用中至关重要,其核心在于确保任务在指定时间内完成。根据截止时间满足的严格程度,实时系统分为硬实时和软实时。硬实时系统要求任务100%满足截止时间,否则可能导致灾难性后果,例如汽车安全系统或医疗设备。软实…...