一、核心存储方案详解
1. SharedPreferences (SP)

使用方式:

// 获取实例
SharedPreferences sp = getSharedPreferences("user_prefs", MODE_PRIVATE);// 写入数据
sp.edit().putString("username", "john_doe").putInt("login_count", 5).apply(); // 异步提交// 读取数据
String username = sp.getString("username", "default");
int loginCount = sp.getInt("login_count", 0);

原理流程:

优点:

  • 简单易用,Android 原生支持

  • 适合存储小量键值对数据

缺点:

  • ⚠️ 全量写入:修改单个值也重写整个文件

  • ⚠️ ANR 风险apply() 异步提交在生命周期回调时可能阻塞主线程

  • ❌ 多进程不安全MODE_MULTI_PROCESS 已废弃

  • ❌ 无类型安全:读取时需手动转换类型

使用场景:
低频修改的简单配置(如用户主题设置、功能开关)


2. MMKV(微信开源)

使用方式:

// build.gradle
implementation 'com.tencent:mmkv:1.3.0'
// 初始化
String rootDir = MMKV.initialize(this);// 获取实例
MMKV kv = MMKV.defaultMMKV();// 写入数据
kv.encode("session_token", "a1b2c3d4");
kv.encode("user_points", 1500);// 读取数据
String token = kv.decodeString("session_token");
int points = kv.decodeInt("user_points");

原理流程:

优点:

  • ⚡ 高性能:读写速度比SP快100倍+

  • 🔒 多进程支持:完善的文件锁机制

  • 📦 高效存储:Protobuf编码节省50%空间

  • 🔐 加密支持:AES加密敏感数据

缺点:

  • ➕ 需引入三方库

  • ⚠️ 数据模型较简单(适合键值对)

使用场景:
高频读写数据(如用户积分)、多进程共享配置、替代SP的所有场景


3. DataStore(Google官方)

使用方式(Preferences DataStore):

// build.gradle
implementation "androidx.datastore:datastore-preferences:1.0.0"
// 定义Key
val USER_NAME = stringPreferencesKey("user_name")
val LOGIN_COUNT = intPreferencesKey("login_count")// 创建DataStore
val dataStore: DataStore<Preferences> = context.createDataStore(name = "settings")// 写入数据
suspend fun saveData(name: String, count: Int) {dataStore.edit { preferences ->preferences[USER_NAME] = namepreferences[LOGIN_COUNT] = count}
}// 读取数据
val userNameFlow: Flow<String> = dataStore.data.map { preferences -> preferences[USER_NAME] ?: "" }

Proto DataStore(类型安全):

// user_prefs.proto
message UserPrefs {string name = 1;int32 login_count = 2;bool is_premium = 3;
}
val Context.userPrefsStore: DataStore<UserPrefs> by dataStore(fileName = "user_prefs.pb",serializer = UserPrefsSerializer
)// 直接操作对象
viewModelScope.launch {context.userPrefsStore.updateData { prefs ->prefs.toBuilder().setLoginCount(10).build()}
}

优点:

  • 🛡️ 类型安全:Protobuf 编译时校验

  • ⚡ 异步操作:基于协程,无主线程阻塞风险

  • 🔄 数据流支持:响应式数据更新

  • 🔄 平滑迁移:提供SP迁移工具

缺点:

  • 📚 学习曲线较陡峭(需掌握协程/Protobuf)

  • 🚫 不支持多进程

使用场景:
新项目开发、复杂数据模型存储、响应式配置更新


二、Intent 数据传输限制

使用方式:

// 传递数据
Intent intent = new Intent(this, DetailActivity.class);
intent.putExtra("user_id", 12345);
intent.putExtra("document", pdfByteArray); // 危险操作!
startActivity(intent);// 接收数据
int userId = getIntent().getIntExtra("user_id", 0);
byte[] pdfData = getIntent().getByteArrayExtra("document");

限制原因:

为什么只能传少量数据?

  1. Binder 限制:IPC传输缓冲区固定为 1MB(Android 8.0+ 部分设备2MB)

  2. 性能问题:大数据序列化/反序列化消耗CPU和内存

  3. 稳定性风险:可能引发OOM或ANR

  4. 生命周期不匹配:Activity可能被销毁重建,丢失数据

解决方案:

数据大小推荐方案示例
< 100KB直接Intent传递intent.putExtra("id", 123)
100KB ~ 1MBFileProvider共享文件传递content:// URI
> 1MB持久化存储+标识传递数据库ID/文件路径
复杂对象Parcelable序列化实现Parcelable接口

三、方案对比与选型指南

维度SharedPreferencesMMKVDataStoreIntent
存储类型键值对键值对键值对/Protobuf对象临时数据
性能极高
线程安全主线程风险安全安全(协程)主线程安全
多进程✅(IPC)
ANR风险高(大数据)
数据大小<1MB无限制无限制<1MB
推荐场景低频配置项高频读写/多进程新项目/类型安全小数据传递

四、常见问题总结

Q1:SharedPreferences有什么缺陷?如何优化?

A:
主要缺陷:

  1. 全量写入导致I/O性能差

  2. apply()异步提交可能引发ANR(ActivityThread等待QueuedWork)

  3. 多进程不安全(MODE_MULTI_PROCESS已废弃)

  4. 无类型安全检查

优化方案:

  1. 迁移到MMKV或DataStore

  2. 避免存储超过1MB数据

  3. 对高频修改项单独拆分文件

Q2:MMKV为什么比SharedPreferences快?

A:
MMKV通过三重优化实现高性能:

  1. mmap内存映射:文件直连内存,省去系统调用和数据拷贝

  2. Protobuf编码:比XML节省50%+存储空间

  3. 增量更新:只追加修改数据,避免全文件重写

  4. 多进程锁:通过文件锁实现安全并发访问

Q3:DataStore相比SP的核心优势?

A:
DataStore的四大优势:

  1. 无ANR设计:协程异步API彻底避免主线程阻塞

  2. 类型安全:Proto DataStore支持编译时类型检查

  3. 响应式编程:通过Flow实现数据变更监听

  4. 事务支持edit{}块内操作保证原子性

Q4:Intent为什么不能传大数据?

A:
Intent传输受限于三点:

  1. Binder IPC限制:传输缓冲区固定1-2MB

  2. 序列化开销:大数据序列化消耗CPU/内存,可能导致ANR

  3. 生命周期风险:Activity重建时系统可能丢弃Intent数据

解决方案:

  • <1MB:直接使用Intent

  • 1-10MB:通过FileProvider传递URI

  • 10MB:持久化存储后传递标识符


五、场景选择


六、高频问题总结

  1. SP的apply()commit()区别?

    apply()异步提交但不返回结果,commit()同步提交并返回boolean结果。注意apply()可能导致ANR。

  2. MMKV如何保证多进程安全?

    通过fcntl文件锁实现写互斥,跨进程场景使用pthread_mutex(需处理robust属性)。

  3. DataStore如何从SP迁移?

    val dataStore = createDataStore(preferencesMigration = SharedPreferencesMigration(context, "sp_name"))

  4. Intent传递大Bitmap的正确方式?

    // 步骤1:保存到文件
    File file = saveBitmapToCache(bitmap); // 步骤2:通过FileProvider生成URI
    Uri uri = FileProvider.getUriForFile(context, "com.example.provider", file);// 步骤3:传递URI并设置权限
    intent.putExtra("image_uri", uri);
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
  5. 为什么推荐用FileProvider不用绝对路径?

    FileProvider提供临时权限控制,避免直接暴露文件路径的安全风险

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/90643.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/90643.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/90643.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

无 sudo 权限的环境下将 nvcc (CUDA Toolkit) 安装到个人目录 linux

要在无 sudo 权限的环境下将 nvcc 安装到 home 个人目录&#xff0c;你可以手动安装 CUDA Toolkit 到你的 $HOME 目录&#xff0c;只需以下几步即可使用 nvcc 编译 CUDA 程序。 ✅ 步骤&#xff1a;本地安装 CUDA Toolkit&#xff08;含 nvcc&#xff09; 下载 CUDA Toolkit Ru…

从指标定义到AI执行流:衡石SENSE 6.0的BI PaaS如何重构ISV分析链路

一、痛点&#xff1a;ISV行业解决方案的“三重断链”传统ISV构建行业分析模块时面临的核心挑战&#xff1a;指标定义碎片化&#xff1a;客户A的“销售额”含税&#xff0c;客户B不含税&#xff0c;衍生指标无法复用&#xff1b;分析-执行割裂&#xff1a;发现库存异常后需人工导…

构建跨平台远程医疗系统中的视频通路技术方案探究

一、远程医疗走向日常化&#xff0c;音视频能力成为关键基础设施 随着医疗数字化与分级诊疗体系的不断演进&#xff0c;远程医疗正从试点探索阶段&#xff0c;逐步迈向常态化、标准化应用。从县域医院远程问诊、基层医疗协作&#xff0c;到大型三甲医院的术中协同、专科教学直…

Blackbox Exporter Docker 安装配置,并与 Prometheus 集成

1. 创建配置文件目录bashmkdir -p ~/docker/blackbox/config cd ~/docker/blackbox2. 创建 Blackbox Exporter 配置文件 config/blackbox.ymlyamlmodules:http_2xx: # HTTP 可用性检测(响应 2xx/3xx 状态码)prober: httphttp:valid_http_versions: ["HTTP/1.1", &qu…

杰理通用MCU串口+AT指令+485通讯工业语音芯片

一、概述 在现代智能设备与自动化系统中&#xff0c;语音交互功能日益普及&#xff0c;通用 MCU 语音芯片作为核心组件&#xff0c;承担着关键的语音处理任务。其强大的功能不仅体现在语音合成、识别等方面&#xff0c;还包括高效的通信能力。串口 AT 指令 485 通讯模式为通用…

Krpano 工具如何调节全景图片切割之后的分辨率

文章目录概要第一步1.1 复制一下这个文件中的key &#xff0c;打开 krpano Tools.exe第二步 修改切片之后的分辨率修改前的效果修改后的效果概要 前端渲染全景图模拟3D场景 Krpano 工具 获取到后的默认图片分辨率是2048*2048的&#xff0c;如果觉得分辨率低了可以自行在工具中…

物联网十大应用领域深度解析

一、智能物流技术基础&#xff1a;RFID、无线传感器网络、互联网与运筹学、供应链管理理论结合 应用场景&#xff1a;仓储管理&#xff1a;RFID标签实现库存实时监控&#xff0c;自动补货系统降低缺货率。配送优化&#xff1a;通过GPS与物联网数据分析规划最优路径&#xff0c;…

ElasticSearch基础数据查询和管理详解

目录 一、 ElasticSearch核心概念 1. 全文搜索&#xff08;Full-Text Search&#xff09; 2. 倒排索引&#xff08;Inverted Index&#xff09; 3. ElasticSearch常用术语 3.1 映射&#xff08;Mapping&#xff09; 3.2 索引&#xff08;Index&#xff09; 3.3 文档&…

SSE与Websocket有什么区别?

SSE&#xff08;Server-Sent Events&#xff09;和WebSocket都能实现服务器与客户端的实时通信&#xff0c;但它们在协议设计、应用场景和技术特性上有明显差异。以下从多个维度对比两者的区别&#xff1a; 1. 协议基础 SSE 基于HTTP协议&#xff0c;是HTTP的扩展。使用单向通…

力扣Hot100疑难杂症汇总

写在前面 这一篇博客主要用来记录力扣Hot100中我反复刷&#xff0c;但又反复错的难题&#xff0c;为了防止秋招手撕的时候尬住&#xff0c;写这篇博客记录一下那些容易遗忘而且对我来说难度较大的题目。后面复习的时候重点对着这个名单来刷题。 二叉树部分 114. 二叉树展开为…

硬核接线图+配置步骤:远程IO模块接入PLC全流程详解

远程IO模块和PLC&#xff08;可编程逻辑控制器&#xff09;的连接涉及多个方面&#xff0c;包括硬件准备、软件配置、接线方法以及注意事项等。PLC品牌大多分为国产、欧系、美系、日系。国产PLC主要有汇川、台达、和利时、信捷等品牌&#xff1b;欧美系PLC以西门子、施耐德、罗…

【数据结构】长幼有序:树、二叉树、堆与TOP-K问题的层次解析(含源码)

为什么我们要学那么多的数据结构&#xff1f;这是因为没有一种数据结构能够去应对所有场景。我们在不同的场景需要选择不同的数据结构&#xff0c;所以数据结构没有好坏之分&#xff0c;而评估数据结构的好坏要针对场景&#xff0c;就如我们已经学习的结构而言&#xff0c;如果…

wps dispimg python 解析实现参考

在 wps excel 中&#xff0c;可以把图片嵌入单元格&#xff0c;此时会图片单元格会显示如下内容 DISPIMG("ID_142D0E21999C4D899C0723FF7FA4A9DD",1)下面是针对这中图片文件的解析实现 参考博客&#xff1a;Python读取wps中的DISPIMG图片格式_wps dispimg-CSDN博客:h…

Java学习---Spring及其衍生(下)

接下来就到了Spring的另外2个知名的衍生框架&#xff0c;SpringBoot和SpringCloud。其中&#xff0c;SpringBoot 是由 Pivotal 团队开发的一个基于 Spring 的框架&#xff0c;它的设计目的是简化 Spring 应用程序的初始搭建和开发过程。SpringBoot 遵循 “约定优于配置” 的原则…

残月头像阁

残月头像阁 使用说明: 直接上传服务器即可## 项目简介残月头像阁是一个简洁美观的头像网站开源程序 支持快速部署与自定义采用拟态(Neumorphism)设计风格&#xff0c;提供多种分类的头像## 功能特性- &#x1f5bc;️ 多分类头像展示&#xff08;男生、女生、卡通、情侣、动漫&…

文献综述AI生成免费工具推荐:高效整理文献

做学术研究时&#xff0c;文献综述无疑是让很多学子和科研工作者头疼的环节。查阅、筛选、梳理大量文献&#xff0c;然后进行归纳总结&#xff0c;最终形成一篇条理清晰的文献综述&#xff0c;这一整个过程常常耗费数日甚至数周。而面对课业压力与紧迫的论文截止时间&#xff0…

OpenCV —— contours_matrix_()_[]

&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️Take your time ! &#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️…

android 小bug :文件冲突的问题

文章目录前言1、问题&#xff1a;两个文件冲突了2、原因&#xff1a;3、结果&#xff1a;后语前言 一个身份证模块识别的小bug&#xff0c;记录一下&#xff0c;这应该是第三次出现&#xff0c;每次出现都不太记得&#xff0c;还是得记录&#xff0c;不然都是重复检索的过程。…

Java学习第七十三部分——Redis

目录 一、前言提要 二、核心特性 三、数据结构 四、应用场景 五、架构模式 六、性能优势 七、客户端库 八、注意事项 九、选择建议 十、使用示例——基于Jedis 和 Lettuce 十一、生态集成——基于Spring Boot 十二、企业级能力 十三、持久化机制 十四、高…

(LeetCode 每日一题) 3487. 删除后的最大子数组元素和 (哈希表)

题目&#xff1a;3487. 删除后的最大子数组元素和 思路&#xff1a;哈希表&#xff0c;时间复杂度0(n)。 维护数组nums的最大值mx&#xff0c;同时用哈希表mp维护数组中非负数出现的情况&#xff0c;记录非负数的和sum。如果哈希表mp的大小为0&#xff0c;那么数组nums都是负数…