MST

星途 面试题库

面试题:Flutter 中 SharedPreferences 与 SQLite 结合的数据迁移问题

假设你已经在 Flutter 应用中使用 SharedPreferences 存储了部分用户配置数据,现在需要将这些数据迁移到 SQLite 数据库中,同时要保证数据的完整性和应用的正常运行,描述你会采取的具体步骤和可能遇到的问题及解决方案。
10.8万 热度难度
前端开发Flutter

知识考点

AI 面试

面试题答案

一键面试

具体步骤

  1. 初始化 SQLite 数据库: 在 Flutter 项目中引入 sqflite 库。通过 openDatabase 方法打开或创建 SQLite 数据库,并定义好表结构。例如,如果 SharedPreferences 中存储的是用户的基本信息,可创建如下表结构:
final Future<Database> database = openDatabase(
  join(await getDatabasesPath(), 'user_config.db'),
  onCreate: (db, version) {
    return db.execute(
      'CREATE TABLE user_config ('
      'id INTEGER PRIMARY KEY AUTOINCREMENT,'
      'key TEXT,'
      'value TEXT'
      ')',
    );
  },
  version: 1,
);
  1. 读取 SharedPreferences 数据: 引入 shared_preferences 库,通过 SharedPreferences.getInstance() 获取实例,然后读取所有存储的数据。例如:
final prefs = await SharedPreferences.getInstance();
final keys = prefs.getKeys();
Map<String, dynamic> prefsData = {};
for (var key in keys) {
  prefsData[key] = prefs.get(key);
}
  1. 将数据插入 SQLite: 遍历从 SharedPreferences 读取的数据,将每条数据插入到 SQLite 数据库对应的表中。例如:
final db = await database;
for (var entry in prefsData.entries) {
  await db.insert(
    'user_config',
    {
      'key': entry.key,
      'value': entry.value.toString()
    },
  );
}
  1. 更新应用读取数据逻辑: 修改应用中读取用户配置数据的逻辑,从 SQLite 数据库读取数据,而不再从 SharedPreferences 读取。例如:
Future<Map<String, dynamic>> getConfigFromDB() async {
  final db = await database;
  final List<Map<String, dynamic>> maps = await db.query('user_config');
  Map<String, dynamic> result = {};
  for (var map in maps) {
    result[map['key']] = map['value'];
  }
  return result;
}

可能遇到的问题及解决方案

  1. 数据类型转换问题
    • 问题:SharedPreferences 存储的数据类型多样(如 int、bool、String 等),而 SQLite 中可能需要统一处理为字符串存储,在读取时可能需要进行类型转换。
    • 解决方案:在插入 SQLite 时,将所有数据先转换为字符串存储。读取时,根据数据的原始类型进行相应转换。例如,对于存储为字符串的整数,可以使用 int.parse() 方法转换回整数类型。
  2. 数据库操作异常
    • 问题:在 SQLite 数据库操作过程中,如打开数据库、插入数据时可能会出现异常,例如数据库文件权限问题、SQL 语句错误等。
    • 解决方案:使用 try - catch 块捕获异常。在打开数据库时,处理 DatabaseException 异常,如权限不足等问题时给出相应提示。在插入数据时,同样捕获异常并处理,例如 SQL 语句语法错误时进行修正。
  3. 数据一致性问题
    • 问题:在迁移过程中,如果应用突然崩溃,可能导致部分数据迁移成功,部分失败,造成数据不一致。
    • 解决方案:可以采用事务机制。在开始迁移数据前,开启一个事务,将所有插入操作放在事务内执行。如果其中任何一个操作失败,事务回滚,保证数据的一致性。例如:
await db.transaction((txn) async {
  for (var entry in prefsData.entries) {
    await txn.insert(
      'user_config',
      {
        'key': entry.key,
        'value': entry.value.toString()
      },
    );
  }
});