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.dart 的 main 函数中完成初始化(全局仅执行一次):

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 管理订单等复杂关系数据,充分发挥各方案的优势。

相关推荐
Geek_Vison6 小时前
保险APP已经用了Flutter,还能接入小程序吗?
flutter·小程序·uni-app·mpaas·小程序容器
FungLeo7 小时前
成为全栈·Flutter App 篇·go_router 与四 Tab App Shell:保留导航状态、深链和登录回跳
flutter·移动开发·成为全栈·go_router·路由设计·深链接
m0_738185827 小时前
Flutter 鸿蒙化实战:screen_protector 适配 OpenHarmony,防截屏/防泄露
flutter·华为·harmonyos·鸿蒙
梦想的颜色12 小时前
【编程实战】AI 时代 APP 开发全栈硬核指南:技术选型 + AI 架构 + 模型落地全维度决策
python·flutter·react native·react.js·ai·桌面应用·milvus
yuanlaile1 天前
2026年全新Flutter 跨平台开发全栈学习资料整理
flutter·getx·鸿蒙 next·flutter开发鸿蒙·flutter入门实战·flutter全栈
恋猫de小郭2 天前
Genkit Dart 1.0 发布,Flutter 原生的 AI Agent 终于完整了
android·前端·flutter
第10086个小白2 天前
flutter桌面端打包方式(Inno Setup Compiler)版本
前端·flutter
陆断枫2 天前
Flutter 3.47 动画引擎盘点:Impeller 全平台,和那些"新特性"
flutter
程序员老刘2 天前
Flet 1.0 思路很好,可惜来晚了
flutter·ai编程·客户端
m0_738185823 天前
Flutter 鸿蒙化实战:qr_code_scanner_plus 适配 OpenHarmony,二维码扫描
flutter·华为·harmonyos·鸿蒙