Flutter 数据存储之 SharedPreferences 键值对存储

目录

一、简介

二、核心概念

三、使用步骤

1. 添加依赖

2. 导入包

3. 获取实例

4. 数据操作方法

四、工程化封装

4.1 为什么要封装?

4.2 统一键值管理:SPKeys

4.3 工具类实现:SPUtils

4.4 在项目中使用

4.5 小结

五、总结


一、简介

        SharedPreferences Flutter 官方提供的轻量级本地数据存储方案,适用于保存用户配置、登录状态、简单设置等键值对(Key-Value)数据。

        其底层基于平台原生实现(Android 的 SharedPreferences 和 iOS 的 NSUserDefaults),具有操作简单、读写高效的特点。

二、核心概念

特性

说明

数据类型支持

intdoubleboolStringList<String>

存储位置

自动持久化到设备本地

数据持久性

应用卸载时数据会被清除

异步操作

所有读写操作均为异步(Future

跨平台一致性

自动适配 Android/iOS/Web/桌面端

三、使用步骤

1. 添加依赖

# pubspec.yaml
dependencies:
  # 存储键值对数据的轻量级解决方案,适用于保存用户设置、偏好等小型数据。
  shared_preferences: ^2.5.4

2. 导入包

import 'package:shared_preferences/shared_preferences.dart';

3. 获取实例

final prefs = await SharedPreferences.getInstance();

4. 数据操作方法

操作类型

方法签名

示例

写入数据

setInt(String key, int value)

prefs.setInt('age', 25);

setDouble(String key, double value)

prefs.setDouble('price', 9.99);

setBool(String key, bool value)

prefs.setBool('isDark', true);

setString(String key, String value)

prefs.setString('name', 'Tom');

setStringList(String key, List<String> value)

prefs.setStringList('tags', ['a','b']);

读取数据

get(String key) / getInt() / getBool()

prefs.getInt('age') ?? 0;

删除数据

remove(String key)

prefs.remove('tempData');

清空数据

clear()

prefs.clear();

四、工程化封装

        在 Flutter 开发中,shared_preferences (SP) 几乎是每个项目的标配,但在实际搬砖过程中,如果直接在业务层满大街写 SharedPreferences.getInstance(),不仅代码显得臃肿,后期维护 Key 值更是一场灾难。今天分享一套我在项目中沉淀的 SP 封装方案,通过 工具类化 和 常量化,实现逻辑解耦。

4.1 为什么要封装?

        很多新手喜欢在 initState 里异步获取 SP 实例,这种做法有两个明显的弊端:

  1. 代码重复:每个页面都要写一遍异步等待。

  2. 硬编码:prefs.getString('user_token') 里的字符串一旦写错一个字母,排查起来非常头疼。

        我们的目标是:全局初始化一次,到处同步调用,Key 值统一管理

4.2 统一键值管理:SPKeys

        首先,新建 sp_keys.dart,我们利用私有构造函数,确保 Key 值只在一个地方定义。

/// Description: 定义存储键值对的键
/// CreateDate:  2025/12/22 11:31
/// Author:      agg
class SPKeys {
  SPKeys._(); // 闭合构造函数,防止被实例化

  static const String userToken = 'user_token';
  static const String themeMode = 'theme_mode';
  static const String userInfo = 'user_info';
}

4.3 工具类实现:SPUtils

        在 sp_utils.dart 中,我们引入 late 关键字,通过在应用启动时预加载,将后续的 IO 操作转化为类似同步的调用。

import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';

///
/// Description:    存储键值对数据工具类
/// CreateDate:     2025/12/22 9:54
/// Author:         agg
///
class SPUtils {
  // 使用 late 关键字,如果未初始化就调用会直接报错,方便开发者定位
  static late SharedPreferences _prefs;

  /// 初始化:在 main.dart 中 await SPUtils.init()
  static Future<void> init() async {
    _prefs = await SharedPreferences.getInstance();
  }

  // ==================== 核心方法 ====================
  /// 保存数据
  /// 支持 String, int, double, bool, List<String>
  /// 以及可以通过 jsonEncode 转换的 Map 或 Object
  static Future<bool> set(String key, dynamic value) {
    if (value is String) return _prefs.setString(key, value);
    if (value is int) return _prefs.setInt(key, value);
    if (value is bool) return _prefs.setBool(key, value);
    if (value is double) return _prefs.setDouble(key, value);
    if (value is List<String>) return _prefs.setStringList(key, value);

    // 如果是 Map 或自定义对象,转为 json 字符串存储
    return _prefs.setString(key, jsonEncode(value));
  }

  static String getString(String key, {String defaultValue = ''}) {
    return _prefs.getString(key) ?? defaultValue;
  }

  static int getInt(String key, {int defaultValue = 0}) {
    return _prefs.getInt(key) ?? defaultValue;
  }

  static bool getBool(String key, {bool defaultValue = false}) {
    return _prefs.getBool(key) ?? defaultValue;
  }

  static double getDouble(String key, {double defaultValue = 0.0}) {
    return _prefs.getDouble(key) ?? defaultValue;
  }

  static List<String> getStringList(
    String key, {
    List<String> defaultValue = const [],
  }) {
    return _prefs.getStringList(key) ?? defaultValue;
  }

  /// 获取复杂对象 (Map 或 List)
  /// 读取后需手动转换类型: Map user = SPUtils.getObject('user');
  static dynamic getObject(String key) {
    String? jsonStr = _prefs.getString(key);
    if (jsonStr == null || jsonStr.isEmpty) return null;
    try {
      return jsonDecode(jsonStr);
    } catch (e) {
      print("SPUtils getObject error: $e");
      return null;
    }
  }

  // ==================== 工具方法 ====================
  static bool containsKey(String key) => _prefs.containsKey(key);

  static Future<bool> remove(String key) => _prefs.remove(key);

  static Future<bool> clear() => _prefs.clear();
}

4.4 在项目中使用

  1. 入口预装载 在 main.dart 的 main 函数中,先确保 Flutter 引擎初始化,然后加载 SP。

    void main() async {
      // 必须调用,确保与原生层交互正常
      WidgetsFlutterBinding.ensureInitialized();
      
      // 预装载 SP,耗时极短,但收益巨大
      await SPUtils.init();
      
      runApp(const MyApp());
    }
  2. 业务逻辑层调用 在任何 Widget 或 Controller 里读写数据,都不再需要 await 获取实例。

// 存储 Token
SPUtils.set(SPKeys.userToken, "ey...123");

// 存储复杂的用户信息
Map<String, dynamic> user = {"name": "agg", "age": 18};
SPUtils.set(SPKeys.userInfo, user);

// 获取数据
String token = SPUtils.getString(SPKeys.userToken);

4.5 小结

  • 同步化体验:虽然 SP 的原生 API 是异步的,但通过在 main 函数预加载实例,我们可以像操作内存变量一样操作本地持久化数据。

  • 安全提示:由于使用了 late,如果在 init() 还没完成时就强行调用读取方法,程序会 Crash,所以务必在 runApp 之前完成初始化。

  • 选型建议:SP 适合存储小体量的配置信息(如登录态、主题颜色、引导页状态),如果是大批量的结构化数据,建议使用 Hive SQFlite

五、总结

        SharedPreferences 是 Flutter 生态中最基础的持久化方案,具有上手简单、跨平台兼容的优势,适用于存储小型、非敏感的键值对数据。

官方文档:SharedPreferences API

<think>我们正在处理用户关于Flutter中使用SharedPreferences存储文本的查询。 根据引用[1],我们知道SharedPreferences用于简单的键值对存储,并且有一个完整实例代码的引用。 引用[2]和[3]提到了文件存储,但用户的问题明确是关于SharedPreferences的,所以我们主要关注引用[1]。 用户要求存储文本,而SharedPreferences正好适用于存储基本数据类型,包括字符串(文本)。 步骤: 1. 添加依赖:在pubspec.yaml文件中添加shared_preferences库。 2. 导入包:在需要使用SharedPreferences的Dart文件中导入包。 3. 存储数据:通过SharedPreferences实例调用setString方法存储文本。 4. 读取数据:通过getString方法读取存储的文本。 我们按照示例结构来回答: - 首先,简要介绍SharedPreferences。 - 然后,分步骤说明如何存储和读取文本。 - 提供代码示例(注意:由于用户要求存储文本,我们将使用字符串存储)。 - 最后,生成相关问题。 注意:引用[1]提到了错误处理,我们也要在代码中展示。 代码示例将包括: - 获取SharedPreferences实例(异步操作)。 - 使用setString存储数据。 - 使用getString读取数据。 - 错误处理(如try-catch)。 由于用户要求存储文本,我们以存储一个字符串为例。 另外,根据引用[3],我们不需要处理目录,因为SharedPreferences内部处理了存储位置。 现在,构建回答: </think>### Flutter中使用SharedPreferences存储文本的方法 SharedPreferencesFlutter中用于存储简单键值对数据的轻量级解决方案,特别适合存储文本、布尔值等基本数据类型。以下是具体操作步骤: #### 1. **添加依赖** 在`pubspec.yaml`中添加依赖: ```yaml dependencies: shared_preferences: ^2.2.2 # 请使用最新版本 ``` 运行`flutter pub get`安装 #### 2. **存储文本数据** ```dart import 'package:shared_preferences/shared_preferences.dart'; // 存储文本 Future<void> saveText(String key, String value) async { try { final prefs = await SharedPreferences.getInstance(); await prefs.setString(key, value); // 核心存储方法 print('文本存储成功'); } catch (e) { print('存储失败: $e'); } } // 调用示例 saveText('user_token', 'abc123xyz'); // 存储登录凭证 saveText('welcome_msg', '您好,欢迎使用APP'); // 存储欢迎语 ``` #### 3. **读取文本数据** ```dart // 读取文本 Future<String?> readText(String key) async { try { final prefs = await SharedPreferences.getInstance(); return prefs.getString(key); // 核心读取方法 } catch (e) { print('读取失败: $e'); return null; } } // 调用示例 final token = await readText('user_token'); final welcome = await readText('welcome_msg'); print('令牌: $token'); // 输出: 令牌: abc123xyz ``` #### 4. **删除数据** ```dart Future<void> deleteText(String key) async { final prefs = await SharedPreferences.getInstance(); await prefs.remove(key); // 删除指定键 } ``` #### 关键特性说明 - **存储位置**:数据存储在设备本地,iOS使用`NSUserDefaults`,Android使用`SharedPreferences`[^2] - **数据限制**:适合存储小文本(最大支持几百KB),不适合存储大文件[^1] - **异步操作**:所有方法均需`async/await`处理 - **支持类型**:除文本外,还支持`int`、`double`、`bool`等类型 > ⚠️ 注意事项: > 1. 键名需保持唯一性(如使用前缀`appname_key`) > 2. 敏感数据(如密码)应使用`flutter_secure_storage` > 3. 频繁读写可能影响性能,建议批量操作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值