Skip to content

本地存储

Flutter 应用经常需要在本地保存数据,如用户偏好设置、登录状态、缓存数据等。

SharedPreferences — 键值对存储

SharedPreferences 是最常用的轻量级本地存储方案,适合保存简单的键值对数据。

安装

bash
flutter pub add shared_preferences

基本用法

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

// 获取实例
final prefs = await SharedPreferences.getInstance();

// 写入数据
await prefs.setString('username', '张三');
await prefs.setInt('age', 25);
await prefs.setBool('isLoggedIn', true);
await prefs.setDouble('score', 98.5);
await prefs.setStringList('tags', ['flutter', 'dart']);

// 读取数据
final username = prefs.getString('username');        // '张三' 或 null
final age = prefs.getInt('age');                    // 25 或 null
final isLoggedIn = prefs.getBool('isLoggedIn') ?? false;  // 带默认值

// 删除数据
await prefs.remove('username');

// 清空所有数据
await prefs.clear();

// 检查 key 是否存在
final hasKey = prefs.containsKey('username');

封装 StorageService

dart
class StorageService {
  static StorageService? _instance;
  late SharedPreferences _prefs;

  static Future<StorageService> get instance async {
    _instance ??= StorageService._();
    await _instance!._init();
    return _instance!;
  }

  StorageService._();

  Future<void> _init() async {
    _prefs = await SharedPreferences.getInstance();
  }

  // Token
  String? getToken() => _prefs.getString('token');
  Future<void> setToken(String token) => _prefs.setString('token', token);
  Future<void> removeToken() => _prefs.remove('token');

  // 登录状态
  bool get isLoggedIn => getToken() != null;

  // 主题模式
  String? getThemeMode() => _prefs.getString('theme_mode');
  Future<void> setThemeMode(String mode) => _prefs.setString('theme_mode', mode);

  // 退出登录
  Future<void> logout() async {
    await removeToken();
  }
}

使用:

dart
final storage = await StorageService.instance;
if (storage.isLoggedIn) {
  // 跳转首页
}
await storage.setToken('xxx');

SharedPreferences 适用场景

适合不适合
用户设置(主题、语言)大量结构化数据
登录 Token需要查询的数据
简单标志位频繁更新的数据
少量缓存敏感数据(密码等)

文件读写

当需要存储较大数据(如图片、JSON 文件)时,使用文件读写。

安装

bash
flutter pub add path_provider

获取目录

dart
import 'package:path_provider/path_provider.dart';

// 应用专属临时目录(可能被系统清除)
final tempDir = await getTemporaryDirectory();

// 应用专属文档目录(不会被清除)
final docDir = await getApplicationDocumentsDirectory();

// 外部存储目录(Android)
final externalDir = await getExternalStorageDirectory();

读写文件

dart
import 'dart:io';

// 写入文件
Future<void> writeFile(String fileName, String content) async {
  final dir = await getApplicationDocumentsDirectory();
  final file = File('${dir.path}/$fileName');
  await file.writeAsString(content);
}

// 读取文件
Future<String?> readFile(String fileName) async {
  final dir = await getApplicationDocumentsDirectory();
  final file = File('${dir.path}/$fileName');
  if (await file.exists()) {
    return await file.readAsString();
  }
  return null;
}

// 删除文件
Future<void> deleteFile(String fileName) async {
  final dir = await getApplicationDocumentsDirectory();
  final file = File('${dir.path}/$fileName');
  if (await file.exists()) {
    await file.delete();
  }
}

读写 JSON 文件

dart
import 'dart:convert';

// 写入
Future<void> saveData(String key, Map<String, dynamic> data) async {
  final dir = await getApplicationDocumentsDirectory();
  final file = File('${dir.path}/$key.json');
  await file.writeAsString(jsonEncode(data));
}

// 读取
Future<Map<String, dynamic>?> loadData(String key) async {
  final dir = await getApplicationDocumentsDirectory();
  final file = File('${dir.path}/$key.json');
  if (await file.exists()) {
    final content = await file.readAsString();
    return jsonDecode(content) as Map<String, dynamic>;
  }
  return null;
}

数据库简介

对于需要复杂查询的大量结构化数据,使用数据库更合适。

sqflite

bash
flutter pub add sqflite

sqflite 是最常用的 SQLite 数据库包,适合存储需要查询和关联的数据。

drift (原 moor)

bash
flutter pub add drift
flutter pub add drift_flutter

drift 是基于 SQLite 的高级 ORM 框架,支持类型安全的查询、代码生成等。

建议

  • 简单键值对 → SharedPreferences
  • 中等数据 / 文件缓存 → 文件读写
  • 大量结构化数据 → sqflite / drift

本地存储方案对比

方案适用场景复杂度查询能力
SharedPreferences简单键值对
文件读写大块数据、缓存⭐⭐
sqflite结构化数据、查询⭐⭐⭐SQL
drift类型安全的数据库⭐⭐⭐⭐ORM

下一步

基于 Flutter 官方文档整理