常用第三方库:shared_preferences数据持久化
常用第三方库:shared_preferences数据持久化
前言
shared_preferences是Flutter中最常用的轻量级数据持久化解决方案,它提供了一个简单的key-value存储机制,适合存储用户配置、应用设置等小型数据。本文将从实战角度深入讲解shared_preferences的使用技巧和最佳实践。
基础概念
什么是shared_preferences?
shared_preferences是Flutter官方推荐的轻量级数据持久化方案,它在不同平台上使用不同的实现机制:
- iOS:使用NSUserDefaults
- Android:使用SharedPreferences
- Web:使用localStorage
- Windows/macOS/Linux:使用本地文件存储
特点和适用场景
-
特点:
- 轻量级,适合存储小量数据
- 异步API,不阻塞主线程
- 支持基本数据类型
- 跨平台兼容
- 无需数据库配置
-
适用场景:
- 用户偏好设置
- 应用配置信息
- 主题、语言等UI配置
- 简单的缓存数据
- 用户登录状态
实战应用
1. 基本使用方法
首先在pubspec.yaml中添加依赖:
dependencies:shared_preferences: ^2.2.0
基本读写操作示例:
import 'package:shared_preferences.dart';class PreferencesManager {static late SharedPreferences _prefs;// 初始化static Future<void> init() async {_prefs = await SharedPreferences.getInstance();}// 存储数据static Future<bool> setString(String key, String value) async {return await _prefs.setString(key, value);}// 读取数据static String getString(String key, {String defaultValue = ''}) {return _prefs.getString(key) ?? defaultValue;}// 删除数据static Future<bool> remove(String key) async {return await _prefs.remove(key);}// 清空所有数据static Future<bool> clear() async {return await _prefs.clear();}
}
2. 实战案例:用户配置管理系统
下面我们通过一个完整的用户配置管理系统来展示shared_preferences的实际应用:
import 'package:flutter/material.dart';
import 'package:shared_preferences.dart';class AppSettings {static const String themeKey = 'app_theme';static const String languageKey = 'app_language';static const String fontSizeKey = 'font_size';static late SharedPreferences _prefs;// 初始化static Future<void> init() async {_prefs = await SharedPreferences.getInstance();}// 主题设置static Future<void> setDarkMode(bool isDark) async {await _prefs.setBool(themeKey, isDark);}static bool isDarkMode() {return _prefs.getBool(themeKey) ?? false;}// 语言设置static Future<void> setLanguage(String languageCode) async {await _prefs.setString(languageKey, languageCode);}static String getLanguage() {return _prefs.getString(languageKey) ?? 'en';}// 字体大小设置static Future<void> setFontSize(double size) async {await _prefs.setDouble(fontSizeKey, size);}static double getFontSize() {return _prefs.getDouble(fontSizeKey) ?? 14.0;}
}// 使用Provider进行状态管理
class AppSettingsProvider extends ChangeNotifier {bool _isDarkMode;String _language;double _fontSize;AppSettingsProvider() :_isDarkMode = AppSettings.isDarkMode(),_language = AppSettings.getLanguage(),_fontSize = AppSettings.getFontSize();bool get isDarkMode => _isDarkMode;String get language => _language;double get fontSize => _fontSize;Future<void> toggleTheme() async {_isDarkMode = !_isDarkMode;await AppSettings.setDarkMode(_isDarkMode);notifyListeners();}Future<void> updateLanguage(String newLanguage) async {_language = newLanguage;await AppSettings.setLanguage(newLanguage);notifyListeners();}Future<void> updateFontSize(double newSize) async {_fontSize = newSize;await AppSettings.setFontSize(newSize);notifyListeners();}
}
3. 性能优化建议
- 批量操作优化
// 使用事务批量处理
Future<void> batchUpdate() async {final prefs = await SharedPreferences.getInstance();await Future.wait([prefs.setString('key1', 'value1'),prefs.setInt('key2', 123),prefs.setBool('key3', true)]);
}
- 缓存实例优化
class PrefsCache {static SharedPreferences? _prefs;static Future<SharedPreferences> get instance async {_prefs ??= await SharedPreferences.getInstance();return _prefs!;}
}
- 数据序列化优化
import 'dart:convert';class UserSettings {final String theme;final String language;final double fontSize;UserSettings({required this.theme, required this.language, required this.fontSize});Map<String, dynamic> toJson() => {'theme': theme,'language': language,'fontSize': fontSize,};factory UserSettings.fromJson(Map<String, dynamic> json) => UserSettings(theme: json['theme'],language: json['language'],fontSize: json['fontSize'],);// 保存到SharedPreferencesFuture<void> save() async {final prefs = await SharedPreferences.getInstance();await prefs.setString('user_settings', jsonEncode(toJson()));}// 从SharedPreferences加载static Future<UserSettings?> load() async {final prefs = await SharedPreferences.getInstance();final String? jsonStr = prefs.getString('user_settings');if (jsonStr == null) return null;return UserSettings.fromJson(jsonDecode(jsonStr));}
}
常见问题与解决方案
-
数据类型限制
- 问题:shared_preferences只支持基本数据类型
- 解决:使用JSON序列化存储复杂对象
-
并发访问问题
- 问题:多处同时写入可能造成数据不一致
- 解决:使用单例模式和锁机制
-
存储空间限制
- 问题:不适合存储大量数据
- 解决:使用数据库或文件存储大型数据
面试题解析
-
Q:shared_preferences与SQLite的区别是什么?何时使用它们?
A:主要区别在于:- shared_preferences:
- 适合存储简单的key-value数据
- 数据量小
- 无需复杂查询
- 适合存储配置信息
- SQLite:
- 支持复杂的数据结构
- 可以存储大量数据
- 支持SQL查询
- 适合存储业务数据
- shared_preferences:
-
Q:如何在shared_preferences中安全地存储敏感数据?
A:shared_preferences不适合存储敏感数据,建议:- 使用flutter_secure_storage等安全存储插件
- 对敏感数据进行加密后再存储
- 使用系统的钥匙串/密钥库服务
-
Q:shared_preferences的存储限制是什么?如何处理大量数据?
A:- 存储限制:
- Android:无硬性限制,但建议控制在几MB以内
- iOS:单个key的值限制为4KB
- 处理大量数据的方案:
- 分片存储
- 使用数据库
- 使用文件存储
- 使用云存储
- 存储限制:
总结
shared_preferences是Flutter中非常实用的数据持久化方案,特别适合存储应用配置和用户偏好等小型数据。通过本文的学习,我们掌握了:
- shared_preferences的基本使用方法
- 实际项目中的应用场景和最佳实践
- 性能优化技巧和注意事项
- 常见问题的解决方案
在实际开发中,建议结合具体需求选择合适的存储方案,对于配置类的小型数据,shared_preferences是最佳选择。
参考资源
- Flutter官方文档:https://flutter.dev/docs/cookbook/persistence/key-value
- shared_preferences包文档:https://pub.dev/packages/shared_preferences
- Flutter存储最佳实践:https://flutter.dev/docs/cookbook/persistence
本文介绍了Flutter中shared_preferences的使用方法和最佳实践,通过实际案例和面试题解析,帮助读者更好地理解和应用这个重要的数据持久化工具。如果你有任何问题或建议,欢迎在评论区留言交流。
相关文章:
常用第三方库:shared_preferences数据持久化
常用第三方库:shared_preferences数据持久化 前言 shared_preferences是Flutter中最常用的轻量级数据持久化解决方案,它提供了一个简单的key-value存储机制,适合存储用户配置、应用设置等小型数据。本文将从实战角度深入讲解shared_prefere…...
项目驱动 CAN-bus现场总线基础教程》随笔
阅读:《项目驱动 CAN-bus现场总线基础教程》 仲裁段的实现 有感而发 感觉出人意外之处 感觉出人意外之处 最近在阅读入门的CAN相关书籍时,在介绍仲裁段是如何实现各节点之间,通讯仲裁功能的章节中,有如下一段描述: …...
WPF之XAML基础
文章目录 XAML基础:深入理解WPF和UWP应用开发的核心语言1. XAML简介XAML与XML的关系 2. XAML语法基础元素语法属性语法集合语法附加属性 3. XAML命名空间命名空间映射关系 4. XAML标记扩展静态资源引用数据绑定相对资源引用常见标记扩展对比 5. XAML与代码的关系XAM…...
测试基础笔记第十四天
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一、字符串1.字符串2.字符串切片3.查找find()4.去除两端空白字符 strip5.字符串转换大小写 lower、upper5.拆分 split()6.字符串的其他常见方…...
Java详解LeetCode 热题 100(01):LeetCode 1. 两数之和(Two Sum)详解
文章目录 1. 题目描述2. 理解题目3. 解法一:暴力枚举法3.1 思路3.2 Java代码实现3.3 代码详解3.4 复杂度分析3.5 适用场景 4. 解法二:哈希表法4.1 思路4.2 Java代码实现4.3 代码详解4.4 复杂度分析4.5 适用场景 5. 解法三:两遍哈希表法5.1 思…...
机器学习之三:归纳学习
正如人们有各种各样的学习方法一样,机器学习也有多种学习方法。若按学习时所用的方法进行分类,则机器学习可分为机械式学习、指导式学习、示例学习、类比学习、解释学习等。这是温斯顿在1977年提出的一种分类方法。 有关机器学习的基本概念,…...
AI声像融合守护幼儿安全——打骂/异常声音报警系统的智慧防护
幼儿园是孩子们快乐成长的摇篮,但打骂、哭闹或尖叫等异常事件可能打破这份宁静,威胁幼儿的身心安全。打骂/异常声音报警系统,依托尖端的AI声像融合技术,结合语音识别、情绪分析与视频行为检测,为幼儿园筑起一道智能安全…...
2024ICPC网络赛第二场题解
文章目录 F. Tourist(签到)I. Strange Binary(思维)J. Stacking of Goods(思维)A. Gambling on Choosing Regionals(签到)G. Game(数学)L. 502 Bad Gateway(数学)E. Escape(BFS)C. Prefix of Suffixes(kmp结论)K. match(01trie分治多项式乘法组合数) 题目链接 F. Tourist(签到…...
风控策略引擎架构设计全解析:构建智能实时决策系统
摘要 本文深入探讨现代风控策略引擎的核心架构设计,结合金融反欺诈、电商交易风控等典型场景,详细解析实时决策、规则引擎、特征计算等关键技术模块的实现方案。通过分层架构设计、分布式计算优化、策略动态编排等创新方法,展示如何构建支撑每秒万级决策的高可用风控系统。…...
TensorFlow 安装全攻略
选择 TensorFlow 的原因: TensorFlow 是一个端到端平台,它提供多个抽象级别,因此您可以根据自己的需求选择合适的级别。您可以使用高阶 Keras API 构建和训练模型,该 API 让您能够轻松地开始使用 TensorFlow 和机器学习。如果您需…...
Dijkstra 算法代码步骤[leetcode.743网络延迟时间]
有 n 个网络节点,标记为 1 到 n。 给你一个列表 times,表示信号经过 有向 边的传递时间。 times[i] (ui, vi, wi),其中 ui 是源节点,vi 是目标节点, wi 是一个信号从源节点传递到目标节点的时间。 现在,…...
Ubuntu22.04/24.04 P104-100 安装驱动和 CUDA Toolkit
硬件环境 使用一块技嘉 B85m-DS3H 安装 P104-100, CPU是带集成显卡的i5-4690. 先在BIOS中设置好显示设备优先使用集成显卡(IGX). 然后安装P104-100开机. 登入Ubuntu 后查看硬件信息, 检查P104-100是否已经被检测到 # PCI设备 lspci -v | grep -i nvidia lspci | grep NVIDIA …...
Golang 学习指南
目录 变量与常量数据类型与控制结构常用数据结构函数与错误处理指针与并发Gin 框架与 go mod小结与参考资料 1. 变量与常量 变量(var) 用于定义可变的值。可以指定类型,也可以自动推断类型。示例:var name string "Golang…...
Ubuntu 磁盘空间占用清理(宝塔)
目录 前言1. 基本知识2. 实战 前言 🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF 爬虫神器,无代码爬取,就来:bright.cn 本身自搭建了一个宝塔,突然一下子多了好些空…...
AntBio: 2025 AACR Meeting - Charting New Oncology Frontiers Together
AntBio cordially invites you to attend the 2025 AACR Annual Meeting and jointly chart a new course in oncology research! The global benchmark for cancer research and therapeutics—the 2025 American Association for Cancer Research (AACR) Annual Meeting—wi…...
数模学习:二,MATLAB的基本语法使用
注释代码: (1)在每行语句后面加上分号,则不显示该行代码的运算结果。 在每行代码前加%,则该行代码会被注释掉 (2) 多行注释: 选中要注释的多行语句,按快捷键Ctrl R (3) 取消注释: 选中要注释的多行语句…...
【Webpack \ Vite】多环境配置
环境变量脚本命令 如何通过不同的环境变量或不同的配置文件进行项目区分,动态加载配置。通常,使用环境变量是最简单且灵活的方法,因为它不需要改变构建命令或创建多个配置文件 环境变量 在根目录下创建 .env.xxx 文件,为不同的环…...
已知漏洞打补丁
. 打补丁 根据MS漏洞编号或者CVE漏洞编号都可以找到对应的HotfixID。 1.根据MS漏洞编号可以使用:https://learn.microsoft.com/zh-cn/security-updates/securitybulletins/securitybulletins 即可找到KB编号。 2.根据CVE漏洞编号可以使用:https://cve…...
WGS84(GPS)、火星坐标系(GCJ02)、百度地图(BD09)坐标系转换Java代码
在做基于百度地图、高德地图等电子地图做为地图服务的二次开发时,通常需要将具有WGS84等坐标的矢量数据(如行政区划、地名、河流、道路等GIS地理空间数据)添加到地图上面。 然而,在线地图大多使用的是火星坐标系,需要…...
R语言操作n
1.加载安装vegan包 2.查看data(varechem)和data(varespec),探索其维度和结构 3.基于varespec构建物种互作网络,输出gml文件并采用gephi可视化为图片,输出pdf,阈值为r>0.6,p<0.05 4.基于varespec和varechem构建物种-环境互作…...
ChatGPT与DeepSeek在科研论文撰写中的整体科研流程与案例解析
随着人工智能技术的快速发展,大语言模型如ChatGPT和DeepSeek在科研领域展现出强大的潜力,尤其是在论文撰写方面。本文旨在介绍如何利用ChatGPT和DeepSeek提升科研论文撰写的效率与质量,并提供一个具体案例,详细阐述其技术流程及公…...
VScode在 Markdown 编辑器中预览
1. 使用在线 Mermaid 编辑器 步骤: 打开 Mermaid Live Editor。将你 .md 文件中的 Mermaid 代码(从 mermaid 到结束的代码块)复制粘贴到编辑器的左侧输入框。编辑器会自动在右侧生成可视化的 ER 图。你可以点击右上角的下载按钮,…...
驱动开发硬核特训 · Day 22(下篇): # 深入理解 Power-domain 框架:概念、功能与完整代码剖析
一、Power-domain 框架基础概念 ✏️ 什么是 Power-domain? 在 Linux 内核中,Power-domain(电源域) 是指一组硬件模块的逻辑集合,这些模块可以被统一控制电源状态(上电、断电)。 Linux 内核通…...
无人机超声波避障技术要点与难点!
一、超声波避障技术要点 4. 障碍物建模 通过最小二乘法平面拟合,将单点测距数据转化为障碍物表面模型,提高避障准确性。 使用队列(wallqueue)存储障碍物信息,并进行去重处理,避免重复避障。 5. 避障轨…...
ASCII字符编码标准及字符表
目录 概述 1 标准 ASCII 表(0-127) 2 大写字母(A-Z) 3 小写字母(a-z) 4 说明 概述 ASCII(American Standard Code for Information Interchange,美国信息交换标准代码ÿ…...
联想昭阳笔记本 风扇一键静音优化操作指南
【联想昭阳笔记本 一键静音优化操作指南】 第1步:安装官方工具 Lenovo Vantage 打开【开始菜单】→ 搜索【Microsoft Store】,打开。在 Store 里搜索【Lenovo Vantage】,下载安装。安装好后,打开【Lenovo Vantage】。进入【设备…...
go语言八股文(三)
1.java和go的区别 1. 语言设计目标 Java: 通用性:设计为一种通用的、面向对象的编程语言,适用于多种应用场景,如桌面应用、服务器端应用、移动应用等。跨平台性:通过“一次编写,到处运行”(Wr…...
Flutter 学习之旅 之 flutter 有时候部分手机【TextField】无法唤起【输入法软键盘】的一些简单整理
Flutter 学习之旅 之 flutter 有时候部分手机【TextField】无法唤起【输入法软键盘】的一些简单整理 目录 Flutter 学习之旅 之 flutter 有时候部分手机【TextField】无法唤起【输入法软键盘】的一些简单整理 一、简单介绍 二、现象描述 三、尝试的解决方案 1、根据应用的…...
【工具】scMultiMap基于单细胞多模态数据实现增强子与靶基因的细胞类型特异性映射
文章目录 介绍代码参考 介绍 在与疾病相关的细胞类型中绘制增强子和靶基因图谱,能够为全基因组关联研究(GWAS)变异的功能机制提供关键见解。单细胞多模态数据能够测量同一细胞中的基因表达和染色质可及性,从而实现细胞类型特异性…...
rt-linux下的cgroup cpu的死锁bug
一、背景 rt-linux系统有其非常大的实时性的优势,但是与之俱来的是该系统上有一些天然的缺陷。由于rt-linux系统允许进程在内核态执行的逻辑里,在持锁期间,甚至持spinlock锁期间,都能被其他进程抢占。这一特性能带来实时性的好处…...
Java 内存泄漏 详解
Java 内存泄漏是指程序中某些对象不再被使用,但由于某些原因无法被垃圾回收器(Garbage Collector, GC)回收,导致内存被持续占用,最终可能引发性能问题或 OutOfMemoryError。 本文将从底层原理、源码层面详细解释 Java …...
Rabbit MQ的基础认识
零、介绍 MQ:message queue(消息队列:先进先出) Rabbit MQ: 一、优势 1.应用解耦 2.异步提速 3.削峰填谷 4.总结 二、劣势...
GIS开发笔记(16)解决基于osg和osgearth三维地图上添加placeNode图标点击不易拾取的问题
一、实现效果 二、实现原理 在图标添加的位置同时添加一个红色圆球,半径为5000~8000米,图标和圆球挂接到同一个group节点,group节点再挂接到根节点,当点击到圆球时,通过遍历父节点就可以找到被点击的图标节点。 三、参考代码 //添加图标代码 #pragma once #include &…...
JDBC 使用流程详解
1. 加载数据库驱动 目的:注册数据库驱动类,使 JDBC 能识别特定数据库(如 MySQL、Oracle)。 代码示例: // JDBC 4.0 后无需显式加载驱动(SPI 自动发现),但部分旧项目仍需手动加载 C…...
小白学习java第16天(上): javaWeb
0.背景介绍 1.前言 首先我们需要javaweb里面的大概流程是干什么的,怎么才能实现的?,每一部分是靠什么进行的?以及背后实现的功能是干什么的?。。。。对于我来说要是不解决这些,会让我感觉不踏实ÿ…...
vue 打包设置
1、vue webpack配置 filename: [path][base].gz,// 设置成这样就行了 const { defineConfig } require(vue/cli-service)const debug process.env.NODE_ENV ! productionconst CompressionWebpackPlugin require(compression-webpack-plugin)const TerserPlugin require(…...
Excel如何安装使用EPM插件并且汉化?
Excel如何使用EPM插件 Excel如何使用EPM插件一、安装EPM插件二、启动EPM插件三、插件汉化设置 Excel如何使用EPM插件 一、安装EPM插件 在安装EPM插件时,若运行安装包后出现报错提示,通常是因为系统缺少 Visual Studio 2010 组件,需先安装该…...
在Linux中使用fcntl函数和ioctl函数
特性fcntlioctl作用对象文件描述符(通用文件操作)设备文件(硬件或驱动控制)标准化程度POSIX 标准,行为一致设备相关,无统一标准典型场景文件锁、非阻塞模式、描述符复制终端控制、网络配置、硬件操作移植性…...
ESP32-S3 入门学习笔记(四):LED实验
ESP32-S3 入门学习笔记(四):LED实验 开发板:正点原子ESP32S3 B站学习链接:link 1. GPIO&LED 简介 1.1 GPIO 简介 GPIO 是负责控制或采集外部器件信息的外设,主要负责输入输出功能。以下是ATK-MWS3S…...
clickhouse#复制修改数据
需求 在ClickHouse表中存在一些数据,你需要复制其中几行数据,这个复制不是完全复制,额外需要修改其中某几列数据项。 语句 INSERT INTO xxx_table SELECT * REPLACE ({except_value_1} AS {column_name_1},...{except_value_n} AS {colum…...
Java安全之cc链学习集合
CC1 InvokerTransformer https://blog.csdn.net/weixin_53912233/article/details/137786954 LazyMap https://blog.csdn.net/weixin_53912233/article/details/137787763 CC1链学习记录_cc1 链子 学习-CSDN博客 Java反序列化Commons-Collections篇02-CC1链补充 | Drunk…...
分享:google高级搜索常用的4个入口
网站和文件:google.com/advanced_search图片:google.com/advanced_image_search视频:google.com/advanced_video_search书籍:google.com/advanced_book_search...
内存四区(堆)
在上一次分享中,我和大家分享了栈区,今天栈区来了。 而内存四区中,堆区是干嘛的呢? 堆区,也是用来存放数据的,只不过呢,堆区中的数据的生死存亡是由程序员来控制的。 当然如果你一直不管堆区…...
Ldap高效数据同步- MirrorMode双主复制模式配置详解(下)
#作者:朱雷 上篇:《Ldap高效数据同步- MirrorMode双主复制模式配置详解(上)》 链接: link 文章目录 三、配置Mirror复制类型3.3. 在ldap-0上增加test2用户3.4. 在ldap-1上查看3.5. 在ldap-1上增加test4用户3.7. 最终两台LDAP数据…...
亚组风险比分析与可视化
1. 结果解读 1.1 风险比概述 1.1.1 风险比基本概念 风险比(Hazard Ratio)用于衡量治疗组与对照组事件发生的风险差异。 风险比为1,表示两组风险相同;小于1,治疗组风险低;大于1,治疗组风险高。 1.1.2 性别亚组分析 A性风险比小于1,表明治疗对A性有积极效果,风险降低。…...
2个小时1.5w字| React Golang 全栈微服务实战
文章目录 前言Golang 入门教程1. 下载与环境配置安装 GoWindows 安装macOS 安装Linux 安装 理解 GOROOT 和 GOPATHGOROOTGOPATHGo Modules 与 GOPATH 的关系查看和设置 Go 环境变量 配置 GOPATH 2. 语法与包管理Go 基础语法运行 Go 程序构建 Go 程序包管理 (Go Modules)常用标准…...
Spring security详细上手教学(三)密码管理
Spring security详细上手教学(三)密码管理 本章节两部分内容 实现PasswordEncoder使用Spring Security Crypto模块提供的工具 1. 使用 password encoder 通常,系统不会使用纯文本来保存密码,需要进行加密/哈希等一系列处理以加…...
ADC读取异常情况汇总
MCU ADC读取内部参考电压 Vrefint 如果某个输入引脚的电压高于供电电压,可能存在读取内部参考电压数值不准或者读数是4095。 虽然宽电压支持,最好硬件设计硬件避免这种情况,避免异常情况。...
给函数参数设置默认值的方式
在 JavaScript 中,给函数参数设置默认值主要有以下几种方式: 1. 函数体内手动检查赋值(ES5 及以前) 在函数内部检查参数是否为 undefined,然后手动赋值默认值。 function greet(name, age) {name name ! undefined…...
【C语言】内存分配的理解
很多时候我们声明变量,系统就自动为我们处理好了内存。 这主要取决于内存分配发生的时间和内存区域。C语言中主要有以下几种内存分配方式: 栈 (Stack) 内存分配 (自动内存): 何时发生: 在函数内部声明的非static局部变量(包括基本类型如 int…...