Flutter 三大主流本地存储全解:SharedPreferences、Hive、SQLite 实战指南

在 Flutter 开发中,本地持久化存储直接影响应用运行性能、开发效率与用户体验 。目前业内最常用的三种方案分别是轻量键值库 SharedPreferences、高性能 NoSQL 数据库 Hive、传统关系型数据库 SQLite(sqflite)。本文会结合使用场景、依赖配置、完整代码、核心特性逐一拆解,并附上选型对照表,帮助你根据业务需求精准选择存储方案。

一、SharedPreferences:轻量级键值存储(基础配置首选)

1. 核心定位与适用场景

SharedPreferences 是 Flutter 官方推荐的轻量键值对存储 ,底层封装了 Android 原生 SharedPreferences 和 iOS 原生 NSUserDefaults,仅支持字符串、数字、布尔值等基础数据类型。

  • ✅ 最佳场景:App 全局配置、主题模式、语言设置、登录状态、功能开关、首次启动标记等小型简单数据
  • ❌ 不适用:大量列表数据、自定义对象、复杂业务数据、高频读写场景。

2. 依赖引入

在项目根目录 pubspec.yaml 中添加依赖,当前稳定版本 2.3.0

yaml

yaml 复制代码
dependencies:
  flutter:
    sdk: flutter
  shared_preferences: ^2.3.0

执行 flutter pub get 完成安装。

3. 完整代码实战(封装工具类)

推荐封装统一工具类,避免重复初始化实例,简化全局调用。示例以主题配置为例,同时拓展增、删、查基础操作:

dart

csharp 复制代码
import 'package:shared_preferences/shared_preferences.dart';

/// 本地配置管理工具类
class SettingsService {
  // 定义存储键名(统一管理,避免硬编码)
  static const String _themeKey = "theme_mode";
  static const String _loginKey = "is_login";

  /// 保存主题模式
  Future<void> saveTheme(String theme) async {
    // 获取 SharedPreferences 单例实例
    final prefs = await SharedPreferences.getInstance();
    // 写入字符串数据
    await prefs.setString(_themeKey, theme);
  }

  /// 读取主题模式(设置默认值为系统跟随)
  Future<String> getTheme() async {
    final prefs = await SharedPreferences.getInstance();
    // 取值,为空时返回默认值
    return prefs.getString(_themeKey) ?? "system";
  }

  /// 保存登录状态(布尔值)
  Future<void> setLoginStatus(bool isLogin) async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setBool(_loginKey, isLogin);
  }

  /// 读取登录状态
  Future<bool> getLoginStatus() async {
    final prefs = await SharedPreferences.getInstance();
    return prefs.getBool(_loginKey) ?? false;
  }

  /// 删除指定配置
  Future<void> deleteTheme() async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.remove(_themeKey);
  }

  /// 清空所有本地配置
  Future<void> clearAllSettings() async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.clear();
  }
}

4. 页面调用示例

dart

csharp 复制代码
// 异步读取主题
void loadTheme() async {
  String theme = await SettingsService().getTheme();
  print("当前主题:$theme");
}

// 切换为深色主题
void switchDarkTheme() async {
  await SettingsService().saveTheme("dark");
}

5. 优缺点总结

  • 优点:接入零成本、API 极简、跨平台兼容、原生系统适配完善。
  • 缺点:仅支持基础数据类型、大数据读写性能差、无加密能力、不支持复杂查询。

二、Hive:高性能 NoSQL 数据库(结构化对象 / 离线缓存首选)

1. 核心定位与适用场景

Hive 是一款纯 Dart 编写的高性能本地 NoSQL 数据库 ,无需原生桥接,读写速度远超 SharedPreferences 和 SQLite,原生支持自定义 Dart 对象,搭配 TypeAdapter 实现类型安全,还支持数据加密。

  • ✅ 最佳场景:离线数据缓存、任务列表、笔记、商品列表等结构化对象数据、中大型数据集;需要数据实时响应 UI 更新的场景。
  • ❌ 不适用:需要多表关联、复杂 SQL 聚合查询的关系型业务。

2. 依赖引入

Hive 分为运行依赖和编译依赖(代码生成器),pubspec.yaml 配置如下:

yaml

yaml 复制代码
dependencies:
  flutter:
    sdk: flutter
  hive: ^2.2.3          # Hive 核心库
  hive_flutter: ^1.1.0  # Flutter 适配插件

dev_dependencies:
  hive_generator: ^2.0.1  # 代码生成器(生成对象适配器)
  build_runner: ^2.4.0    # Dart 构建工具

执行 flutter pub get 安装依赖。

3. 分步实战(模型定义 → 初始化 → CRUD → 响应式 UI)

步骤 1:定义实体模型(Hive 对象)

以任务 Task 模型为例,使用注解标记字段,用于自动生成适配器:

dart

dart 复制代码
import 'package:hive/hive.dart';

/// 任务实体类,typeId 全局唯一(0~255)
@HiveType(typeId: 0)
class Task extends HiveObject {
  /// 任务唯一ID
  @HiveField(0)
  late String id;

  /// 任务标题
  @HiveField(1)
  late String title;

  /// 任务完成状态
  @HiveField(2)
  late bool isDone;

  /// 创建时间
  @HiveField(3)
  late DateTime createdAt;

  // 构造方法
  Task({
    required this.id,
    required this.title,
    required this.isDone,
    required this.createdAt,
  });
}

步骤 2:生成 TypeAdapter(核心步骤)

打开终端,在项目根目录执行命令,自动生成 TaskAdapter 适配器:

bash

运行

arduino 复制代码
dart run build_runner build

执行成功后,会在当前目录生成 task.g.dart 文件,必须在模型文件中引入

dart

dart 复制代码
part 'task.g.dart'; // 追加在 Task 类文件末尾

步骤 3:全局初始化 Hive

main.dartmain 函数中完成初始化(全局仅执行一次):

dart

scala 复制代码
import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'task.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // 初始化 Hive(适配 Flutter 路径)
  await Hive.initFlutter();
  // 注册自定义对象适配器
  Hive.registerAdapter(TaskAdapter());
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: TaskListPage());
  }
}

步骤 4:封装 CRUD 工具类

对 Hive 的 Box(数据容器)进行封装,实现增、查、改、删全操作:

dart

rust 复制代码
import 'package:hive/hive.dart';
import 'task.dart';

class HiveTaskService {
  // 定义 Box 名称(数据容器)
  static const String _taskBoxName = "tasks";

  /// 获取任务 Box 实例
  static Future<Box<Task>> getTaskBox() async {
    return await Hive.openBox<Task>(_taskBoxName);
  }

  /// 新增/更新任务(key 为任务ID,存在则覆盖)
  static Future<void> saveTask(Task task) async {
    final box = await getTaskBox();
    await box.put(task.id, task);
  }

  /// 查询所有任务
  static Future<List<Task>> getAllTasks() async {
    final box = await getTaskBox();
    return box.values.toList();
  }

  /// 根据ID删除任务
  static Future<void> deleteTask(String taskId) async {
    final box = await getTaskBox();
    await box.delete(taskId);
  }

  /// 清空所有任务
  static Future<void> clearAllTasks() async {
    final box = await getTaskBox();
    await box.clear();
  }
}

步骤 5:响应式 UI(数据变化自动刷新)

Hive 原生支持监听 Box 数据变化,搭配 ValueListenableBuilder 实现无状态刷新 ,无需手动调用 setState

dart

less 复制代码
import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'task.dart';
import 'hive_task_service.dart';

class TaskListPage extends StatelessWidget {
  const TaskListPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Hive 任务列表")),
      body: ValueListenableBuilder<Box<Task>>(
        // 监听 tasks 容器数据变化
        valueListenable: Hive.box<Task>("tasks").listenable(),
        builder: (context, box, child) {
          // 实时获取最新任务列表
          List<Task> taskList = box.values.toList();
          if (taskList.isEmpty) {
            return const Center(child: Text("暂无任务"));
          }
          // 列表渲染
          return ListView.builder(
            itemCount: taskList.length,
            itemBuilder: (context, index) {
              Task task = taskList[index];
              return ListTile(
                title: Text(
                  task.title,
                  style: TextStyle(
                    decoration: task.isDone
                        ? TextDecoration.lineThrough
                        : null,
                  ),
                ),
                subtitle: Text("创建时间:${task.createdAt.toLocal().toString().split(".")[0]}"),
                trailing: IconButton(
                  icon: const Icon(Icons.delete, color: Colors.red),
                  onPressed: () => HiveTaskService.deleteTask(task.id),
                ),
              );
            },
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // 模拟新增任务
          Task newTask = Task(
            id: DateTime.now().millisecondsSinceEpoch.toString(),
            title: "新任务 ${DateTime.now().hour}:${DateTime.now.minute}",
            isDone: false,
            createdAt: DateTime.now(),
          );
          HiveTaskService.saveTask(newTask);
        },
        child: const Icon(Icons.add),
      ),
    );
  }
}

4. 进阶特性与补充

  1. 数据加密 :Hive 支持 AES 加密,适合存储隐私数据,搭配 hive_encryption 插件即可实现;
  2. 多 Box 隔离 :不同业务数据拆分到不同 Box,提升读写效率;
  3. 优点:性能极强、原生支持对象存储、类型安全、响应式 UI、跨平台完美兼容;
  4. 缺点:不支持 SQL 语句、无表关联能力,复杂关系数据场景受限。

三、SQLite(sqflite):关系型数据库(复杂查询 / 多表关联首选)

1. 核心定位与适用场景

sqflite 是 Flutter 生态中使用最广泛的 SQLite 封装库,标准关系型数据库,支持完整 SQL 语法、多表关联(JOIN)、聚合查询、事务、索引等数据库能力。

  • ✅ 最佳场景:需要复杂筛选、联表查询、数据统计、事务保证的关系型结构化数据,如订单系统、通讯录、本地账单等。
  • ❌ 不适用:简单配置、纯对象缓存(开发成本高)。

2. 依赖引入

yaml

yaml 复制代码
dependencies:
  flutter:
    sdk: flutter
  sqflite: ^2.3.0       # SQLite 核心库
  path_provider: ^2.1.2 # 获取本地存储路径
  path: ^1.8.3          # 路径拼接工具

执行 flutter pub get 安装。

3. 完整代码实战(数据库初始化 + 表创建 + CRUD)

采用单例模式封装数据库工具类,避免重复创建数据库实例,保证全局唯一连接。

dart

dart 复制代码
import 'dart:io';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart';

/// SQLite 数据库工具类
class DatabaseHelper {
  // 数据库单例
  static Database? _database;

  /// 全局获取数据库实例
  static Future<Database> get database async {
    if (_database != null) return _database!;
    // 初始化数据库
    _database = await _initDatabase();
    return _database!;
  }

  /// 初始化数据库(指定路径 + 创建表)
  static Future<Database> _initDatabase() async {
    // 1. 获取应用私有数据库目录
    Directory appDir = await getApplicationDocumentsDirectory();
    // 2. 拼接数据库完整路径(文件名为 app.db)
    String dbPath = join(appDir.path, "app.db");

    // 3. 打开/创建数据库,版本号用于数据库升级
    return await openDatabase(
      dbPath,
      version: 1,
      // 数据库首次创建时执行(建表语句)
      onCreate: (Database db, int version) async {
        // 创建任务表:id(主键)、title(标题)、is_done(完成状态)、created_at(创建时间)
        await db.execute('''
          CREATE TABLE tasks (
            id TEXT PRIMARY KEY,
            title TEXT NOT NULL,
            is_done INTEGER DEFAULT 0,
            created_at TEXT NOT NULL
          )
        ''');
      },
    );
  }

  /// 新增/更新任务(冲突时覆盖原有数据)
  static Future<void> insertTask(Map<String, dynamic> task) async {
    final db = await database;
    await db.insert(
      "tasks",
      task,
      conflictAlgorithm: ConflictAlgorithm.replace, // 主键冲突则替换
    );
  }

  /// 查询所有任务(按创建时间倒序)
  static Future<List<Map<String, dynamic>>> getAllTasks() async {
    final db = await database;
    // 原生 SQL 查询,支持排序、条件筛选
    return await db.query(
      "tasks",
      orderBy: "created_at DESC",
    );
  }

  /// 根据ID删除任务
  static Future<void> deleteTask(String taskId) async {
    final db = await database;
    await db.delete(
      "tasks",
      where: "id = ?", // 占位符,防止SQL注入
      whereArgs: [taskId],
    );
  }

  /// 清空任务表
  static Future<void> clearTable() async {
    final db = await database;
    await db.delete("tasks");
  }
}

4. 页面调用示例

dart

dart 复制代码
import 'package:flutter/material.dart';
import 'database_helper.dart';

class SqliteTaskPage extends StatefulWidget {
  const SqliteTaskPage({super.key});
  @override
  State<SqliteTaskPage> createState() => _SqliteTaskPageState();
}

class _SqliteTaskPageState extends State<SqliteTaskPage> {
  List<Map<String, dynamic>> _taskList = [];

  // 页面加载时查询数据
  @override
  void initState() {
    super.initState();
    _loadTasks();
  }

  /// 加载所有任务
  Future<void> _loadTasks() async {
    List<Map<String, dynamic>> list = await DatabaseHelper.getAllTasks();
    setState(() {
      _taskList = list;
    });
  }

  /// 新增任务
  Future<void> _addTask() async {
    String taskId = DateTime.now().millisecondsSinceEpoch.toString();
    Map<String, dynamic> newTask = {
      "id": taskId,
      "title": "SQLite 新任务",
      "is_done": 0, // SQLite 无布尔值,用 0(false)/1(true) 替代
      "created_at": DateTime.now().toIso8601String(),
    };
    await DatabaseHelper.insertTask(newTask);
    _loadTasks(); // 刷新列表
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("SQLite 任务列表")),
      body: _taskList.isEmpty
          ? const Center(child: Text("暂无任务"))
          : ListView.builder(
              itemCount: _taskList.length,
              itemBuilder: (context, index) {
                var task = _taskList[index];
                return ListTile(
                  title: Text(task["title"]),
                  trailing: IconButton(
                    icon: const Icon(Icons.delete, color: Colors.red),
                    onPressed: () async {
                      await DatabaseHelper.deleteTask(task["id"]);
                      _loadTasks();
                    },
                  ),
                );
              },
            ),
      floatingActionButton: FloatingActionButton(
        onPressed: _addTask,
        child: const Icon(Icons.add),
      ),
    );
  }
}

5. 补充说明

  1. 数据类型限制 :SQLite 原生无布尔类型,使用 0 代表 false、1 代表 true;时间推荐转为字符串存储;
  2. 数据库升级 :修改 version 版本号,配合 onUpgrade 回调实现表结构升级;
  3. 加密方案 :如需加密,可使用 sqlcipher_flutter_libs 替换原生 SQLite;
  4. 优点:功能完备、支持复杂 SQL、事务、索引、多表关联,适合企业级复杂业务;
  5. 缺点:学习成本高、代码冗余、简单场景下性能不如 Hive。

四、三大存储方案综合选型对照表

结合业务场景、性能、开发成本整理核心选型规则,直接对照选择即可:

表格

业务使用场景 最优存储方案 补充说明
App 配置、主题、语言、登录状态、功能开关 SharedPreferences 极简开发,仅存少量基础类型数据
离线缓存、任务 / 笔记 / 商品列表、自定义对象、响应式 UI Hive 高性能、无需手动序列化,优先推荐
多表关联、复杂筛选、数据统计、事务操作、关系型数据 SQLite(sqflite) 依赖 SQL 能力,复杂业务必备
本地数据需要加密保护 Hive (AES 加密) / SQLCipher 敏感数据专用加密方案

五、总结

  1. 小型配置优先 SharedPreferences:一行代码即可完成读写,是 Flutter 配置存储的标配;
  2. 对象 / 列表缓存优先 Hive:兼顾性能与开发效率,绝大多数离线存储场景的最优解,也是目前社区主流推荐方案;
  3. 复杂关系数据必选 SQLite:当业务出现多表、联表、复杂查询时,关系型数据库的优势无可替代。

实际项目中也可组合使用:例如用 SharedPreferences 存储用户主题配置,Hive 缓存首页列表数据,SQLite 管理订单等复杂关系数据,充分发挥各方案的优势。

相关推荐
悟空瞎说1 小时前
Flutter Isolate 与 compute 全方位实战指南:后台任务优化,保障 UI 60 帧流畅
flutter
风华圆舞2 小时前
Stage 模型下 Flutter 鸿蒙壳工程怎么理解
flutter·华为·harmonyos
●VON2 小时前
AtomGit Flutter鸿蒙客户端:数据模型
android·服务器·安全·flutter·harmonyos·鸿蒙
●VON3 小时前
AtomGit Flutter鸿蒙客户端:收藏仓库
flutter·架构·跨平台·harmonyos·鸿蒙
●VON3 小时前
AtomGit Flutter鸿蒙客户端:主题系统
javascript·flutter·华为·跨平台·harmonyos·鸿蒙
G_dou_4 小时前
Flutter三方库适配OpenHarmony【expense_tracker】消费记录器项目完整实战
flutter·harmonyos
西西学代码4 小时前
Flutter---GlobalKey
flutter
西西学代码4 小时前
Flutter---StatefulBuilder
flutter
●VON6 小时前
AtomGit Flutter鸿蒙客户端:鸿蒙平台集成
flutter·华为·跨平台·harmonyos·鸿蒙