【Flutter 必备插件】数据存储 shared_preferences

shared_preferences 是 Flutter 中最常用的轻量级数据持久化解决方案,它提供了一个简单的 key-value 存储机制,适合存储用户配置、应用设置等小型数据。

基础概念

什么是 shared_preferences

shared_preferences是Flutter官方推荐的轻量级数据持久化方案,在不同的平台中,它基于不同的原生机制开发:

  • iOS:使用 NSUserDefaults
  • Android:使用 PreferencesDataStore
  • Web:使用 localStorage
  • Windows/macOS/Linux:使用本地文件存储

特点和适用场景

特点:

  • 轻量级,适合存储小量数据
  • 异步API,不阻塞主线程
  • 支持基本数据类型
  • 跨平台兼容
  • 无需数据库配置

适用场景:

  • 用户偏好设置
  • 应用配置信息
  • 主题、语言等UI配置
  • 简单的缓存数据
  • 用户登录状态
  • 部分页面数据(首页):在获取首页列表数据时我们常常会先展示旧数据,带给用户更好的体验,不至于一打开页面就是空白的,当我们采用持久化列表数据后,可以直接先展示本地数据,当网络数据请求回来后在进行数据更新。

实战

1. 添加依赖

dependencies:
  shared_preferences: ^2.5.3

2. 封装

library;

import 'package:shared_preferences/shared_preferences.dart';

class SharedPreferencesService {
  late SharedPreferencesWithCache _prefs;

  // 单例模式
  static final SharedPreferencesService _instance = SharedPreferencesService._internal();

  factory SharedPreferencesService() => _instance;

  SharedPreferencesService._internal();

  Future<void> init() async {
    _prefs = await SharedPreferencesWithCache.create(cacheOptions: const SharedPreferencesWithCacheOptions());
  }

  // --- 存储方法 ---

  Future<void> setString(String key, String value) async {
    await _prefs.setString(key, value);
  }

  Future<void> setInt(String key, int value) async {
    await _prefs.setInt(key, value);
  }

  Future<void> setDouble(String key, double value) async {
    await _prefs.setDouble(key, value);
  }

  Future<void> setBool(String key, bool value) async {
    await _prefs.setBool(key, value);
  }

  Future<void> setStringList(String key, List<String> value) async {
    await _prefs.setStringList(key, value);
  }

  // --- 获取方法 ---

  String? getString(String key) => _prefs.getString(key);

  int? getInt(String key) => _prefs.getInt(key);

  double? getDouble(String key) => _prefs.getDouble(key);

  bool? getBool(String key) => _prefs.getBool(key);

  List<String>? getStringList(String key) => _prefs.getStringList(key);

  // --- 删除 & 清除 ---

  Future<void> remove(String key) async {
    await _prefs.remove(key);
  }

  Future<void> clearAll() async {
    await _prefs.clear();
  }
}

3. 使用方式(初始化+调用)

你可以在应用启动时初始化该服务:

main.dart

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  final sharedPreferencesService = SharedPreferencesService();
  await sharedPreferencesService.init();

  runApp(const MyApp());
}

在业务中使用:

// 存储
SharedPreferencesService().setString('username', 'john_doe');
SharedPreferencesService().setBool('is_logged_in', true);

// 读取
String? username = SharedPreferencesService().getString('username');
bool? isLoggedIn = SharedPreferencesService().getBool('is_logged_in');

// 删除
SharedPreferencesService().remove('username');

// 清空所有
SharedPreferencesService().clearAll();

4. 实战案例:用于配置管理系统

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 Future<void> setDarkMode(bool isDark) async {
    await SharedPreferencesService().setBool(themeKey, isDark);
  }
  
  static bool isDarkMode() {
    return SharedPreferencesService().getBool(themeKey) ?? false;
  }
  
  // 语言设置
  static Future<void> setLanguage(String languageCode) async {
    await SharedPreferencesService().setString(languageKey, languageCode);
  }
  
  static String getLanguage() {
    return SharedPreferencesService().getString(languageKey) ?? 'en';
  }
  
  // 字体大小设置
  static Future<void> setFontSize(double size) async {
    await SharedPreferencesService().setDouble(fontSizeKey, size);
  }
  
  static double getFontSize() {
    return SharedPreferencesService().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();
  }
}

5. 性能优化【干货】

  1. 批量操作
// 使用事务批量处理
Future<void> batchUpdate() async {
  await Future.wait([
    SharedPreferencesService().setString('key1', 'value1'),
    SharedPreferencesService().setInt('key2', 123),
    SharedPreferencesService().setBool('key3', true)
  ]);
}
  1. 数据序列化
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'],
  );
  
  // 保存到SharedPreferences
  Future<void> save() async {
    await SharedPreferencesService().setString('user_settings', jsonEncode(toJson()));
  }
  
  // 从SharedPreferences加载
  static Future<UserSettings?> load() async {
    final String? jsonStr = SharedPreferencesService().getString('user_settings');
    if (jsonStr == null) return null;
    return UserSettings.fromJson(jsonDecode(jsonStr));
  }
}

FAQ【干货】

  1. 数据类型限制

    Q:shared_preferences只支持基本数据类型

    A:使用JSON序列化存储复杂对象

  2. 并发访问问题

    Q:多处同时写入可能造成数据不一致

    A:使用单例模式和锁机制

  3. 存储空间限制

    Q:不适合存储大量数据

    A:使用数据库或文件存储大型数据

posted @ 2025-07-14 23:52  YueYa-Tech  阅读(237)  评论(0)    收藏  举报