在 Flutter 开发中,数据持久化是一个很重要的需求。我们需要把数据保存下来,这样即使应用关闭或者设备重启,数据也不会丢失。今天咱就来聊聊几种常见的 Flutter 数据持久化方案,分别是 SharedPreferences、SQLite 和 Hive,看看该怎么选,以及数据迁移的时候该咋办。

一、SharedPreferences 介绍

1. 基本概念

SharedPreferences 就像是一个小盒子,专门用来存放一些简单的数据,比如用户的设置、偏好这些。它操作起来特别简单,就跟往盒子里放东西和从盒子里拿东西一样。

2. 示例代码(Dart 技术栈)

import 'package:shared_preferences/shared_preferences.dart';

// 保存数据
Future<void> saveData() async {
  // 获取 SharedPreferences 实例
  SharedPreferences prefs = await SharedPreferences.getInstance();
  // 保存一个字符串数据
  await prefs.setString('username', 'JohnDoe'); 
  // 保存一个布尔值数据
  await prefs.setBool('isLoggedIn', true); 
}

// 获取数据
Future<void> getData() async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  // 获取字符串数据
  String? username = prefs.getString('username'); 
  // 获取布尔值数据
  bool? isLoggedIn = prefs.getBool('isLoggedIn'); 
  print('Username: $username');
  print('Is Logged In: $isLoggedIn');
}

3. 应用场景

适合保存一些简单的、少量的数据,比如用户的主题设置、是否开启推送等。

4. 技术优缺点

  • 优点:操作简单,使用方便,对于简单的数据保存非常实用。
  • 缺点:只能保存一些简单的数据类型,比如字符串、布尔值、整数等,不适合保存大量复杂的数据。

5. 注意事项

  • 数据存储是明文的,不太安全,不适合保存敏感信息。
  • 数据存储量有限,不能保存大量的数据。

二、SQLite 介绍

1. 基本概念

SQLite 是一个轻量级的数据库,就像一个大仓库,可以存放很多复杂的数据,而且数据之间还可以有关系。它支持 SQL 语句,我们可以用 SQL 语句来对数据进行增删改查。

2. 示例代码(Dart 技术栈)

import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';

// 创建数据库和表
Future<Database> openDB() async {
  String path = join(await getDatabasesPath(), 'my_database.db');
  return await openDatabase(
    path,
    version: 1,
    onCreate: (db, version) {
      // 创建一个名为 users 的表
      return db.execute(
        'CREATE TABLE users(id INTEGER PRIMARY KEY, name TEXT, age INTEGER)',
      );
    },
  );
}

// 插入数据
Future<void> insertUser() async {
  Database db = await openDB();
  await db.insert(
    'users',
    {'name': 'Jane Smith', 'age': 25},
    conflictAlgorithm: ConflictAlgorithm.replace,
  );
}

// 查询数据
Future<List<Map<String, dynamic>>> queryUsers() async {
  Database db = await openDB();
  return await db.query('users');
}

3. 应用场景

适合保存大量的、结构化的数据,比如用户信息、订单信息等。

4. 技术优缺点

  • 优点:可以保存大量的数据,支持 SQL 语句,方便进行复杂的查询和操作。
  • 缺点:操作相对复杂,需要了解 SQL 语句,而且数据库的创建和管理需要一定的技术。

5. 注意事项

  • 数据库的版本管理很重要,如果数据库结构发生变化,需要进行版本升级。
  • 操作数据库可能会影响性能,尤其是在处理大量数据的时候。

三、Hive 介绍

1. 基本概念

Hive 是一个快速、轻量级的键值数据库,它的性能非常好,而且使用起来也比较简单。它可以保存各种类型的数据,包括自定义的对象。

2. 示例代码(Dart 技术栈)

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

// 初始化 Hive
Future<void> initHive() async {
  var dir = await getApplicationDocumentsDirectory();
  Hive.init(dir.path);
  // 注册自定义类型适配器(如果有)
  // Hive.registerAdapter(MyObjectAdapter()); 
}

// 打开盒子并保存数据
Future<void> saveDataToHive() async {
  await initHive();
  var box = await Hive.openBox('myBox');
  // 保存一个字符串数据
  box.put('message', 'Hello, Hive!'); 
}

// 从盒子中获取数据
Future<void> getDataFromHive() async {
  await initHive();
  var box = await Hive.openBox('myBox');
  String? message = box.get('message');
  print('Message from Hive: $message');
}

3. 应用场景

适合保存一些中等规模的数据,比如缓存数据、用户的收藏列表等。

4. 技术优缺点

  • 优点:性能好,操作简单,支持自定义对象的存储。
  • 缺点:不支持 SQL 语句,对于复杂的查询不太方便。

5. 注意事项

  • 需要注册自定义类型的适配器,如果要保存自定义对象。
  • 盒子的管理需要注意,避免打开过多的盒子影响性能。

四、选型考量

1. 数据量

  • 如果数据量很小,比如只保存几个简单的设置,就可以选择 SharedPreferences。
  • 如果数据量很大,而且需要进行复杂的查询和操作,那么 SQLite 是个不错的选择。
  • 如果数据量中等,而且对性能有一定要求,Hive 会比较合适。

2. 数据类型

  • SharedPreferences 只能保存简单的数据类型。
  • SQLite 可以保存各种类型的数据,并且可以建立关系。
  • Hive 支持自定义对象的存储。

3. 性能要求

  • SharedPreferences 性能一般,适合简单的读写操作。
  • SQLite 在处理大量数据时性能较好,但操作相对复杂。
  • Hive 的性能非常好,读写速度快。

4. 开发难度

  • SharedPreferences 操作最简单,几乎不需要什么技术。
  • SQLite 需要了解 SQL 语句,开发难度相对较高。
  • Hive 的操作也比较简单,但需要处理自定义类型的注册。

五、数据迁移策略

1. 从 SharedPreferences 迁移到 SQLite

如果之前使用 SharedPreferences 保存了一些数据,现在需要迁移到 SQLite,可以按照以下步骤进行:

  • 首先,创建 SQLite 数据库和相应的表。
  • 然后,从 SharedPreferences 中读取数据。
  • 最后,将读取的数据插入到 SQLite 数据库中。
import 'package:shared_preferences/shared_preferences.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';

// 迁移数据
Future<void> migrateFromSharedPrefsToSQLite() async {
  // 获取 SharedPreferences 数据
  SharedPreferences prefs = await SharedPreferences.getInstance();
  String? username = prefs.getString('username');
  bool? isLoggedIn = prefs.getBool('isLoggedIn');

  // 打开 SQLite 数据库
  String path = join(await getDatabasesPath(), 'my_database.db');
  Database db = await openDatabase(
    path,
    version: 1,
    onCreate: (db, version) {
      return db.execute(
        'CREATE TABLE users(id INTEGER PRIMARY KEY, username TEXT, isLoggedIn INTEGER)',
      );
    },
  );

  // 插入数据到 SQLite
  await db.insert(
    'users',
    {'username': username, 'isLoggedIn': isLoggedIn == true ? 1 : 0},
    conflictAlgorithm: ConflictAlgorithm.replace,
  );
}

2. 从 Hive 迁移到 SQLite

如果要从 Hive 迁移到 SQLite,可以这样做:

  • 打开 Hive 盒子,读取数据。
  • 创建 SQLite 数据库和表。
  • 将 Hive 中的数据插入到 SQLite 中。
import 'package:hive/hive.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';

// 迁移数据
Future<void> migrateFromHiveToSQLite() async {
  // 初始化 Hive
  var dir = await getApplicationDocumentsDirectory();
  Hive.init(dir.path);
  var box = await Hive.openBox('myBox');
  String? message = box.get('message');

  // 打开 SQLite 数据库
  String path = join(await getDatabasesPath(), 'my_database.db');
  Database db = await openDatabase(
    path,
    version: 1,
    onCreate: (db, version) {
      return db.execute(
        'CREATE TABLE messages(id INTEGER PRIMARY KEY, message TEXT)',
      );
    },
  );

  // 插入数据到 SQLite
  await db.insert(
    'messages',
    {'message': message},
    conflictAlgorithm: ConflictAlgorithm.replace,
  );
}

六、文章总结

在 Flutter 开发中,SharedPreferences、SQLite 和 Hive 都是很有用的数据持久化方案。SharedPreferences 适合保存简单的少量数据,操作简单但功能有限;SQLite 适合保存大量结构化数据,支持复杂查询但开发难度较高;Hive 性能好,适合中等规模数据和自定义对象的存储。在选择方案时,要根据数据量、数据类型、性能要求和开发难度等因素综合考虑。在数据迁移时,要根据不同的情况采取合适的迁移策略。