在这里插入图片描述

概述

SharedPreferences是Flutter中最常用的本地数据存储库,它提供了一个简单的键值对存储机制。在视力保护提醒应用中,我们使用SharedPreferences来保存用户设置、应用状态等数据。本文将详细讲解如何使用SharedPreferences进行数据持久化,包括数据保存、加载、更新等操作。

SharedPreferences的核心功能

SharedPreferences主要提供以下功能:

  1. 数据持久化 - 将数据保存到本地存储
  2. 键值对存储 - 使用字符串键来存储各种类型的数据
  3. 异步操作 - 所有操作都是异步的,不会阻塞UI
  4. 类型支持 - 支持String、int、double、bool、List等类型

这些功能结合在一起,为应用提供了一个完整的本地数据存储解决方案。

项目依赖配置

在pubspec.yaml中,我们已经配置了所需的依赖:

dependencies:
  flutter:
    sdk: flutter
  shared_preferences: ^2.2.2
  get: ^4.6.5

shared_preferences库提供了SharedPreferences功能,get库用于状态管理。这些依赖都是为了支持鸿蒙系统的Flutter开发。

SharedPreferences初始化

在AppController中,我们初始化SharedPreferences。

AppController类定义

class AppController extends GetxController {
  late SharedPreferences prefs;

  
  void onInit() {
    super.onInit();
    initPreferences();
  }

AppController继承自GetxController,是应用的主要状态管理类。late SharedPreferences prefs用于延迟初始化SharedPreferences实例。onInit方法在Controller初始化时自动调用,这是GetX提供的生命周期方法。在这里调用initPreferences来初始化本地存储。这种设计确保了应用启动时能够正确加载用户的设置和数据。

初始化SharedPreferences

  Future<void> initPreferences() async {
    prefs = await SharedPreferences.getInstance();
    loadSettings();
  }

initPreferences是一个异步方法,用于获取SharedPreferences实例。SharedPreferences.getInstance()返回一个Future,我们需要使用await来等待其完成。获取实例后,立即调用loadSettings()来加载保存的设置。这种设计确保了数据的及时加载,避免了数据不一致的问题。

数据加载

在initPreferences之后,我们调用loadSettings来加载保存的数据。

加载所有设置

void loadSettings() {
  dailyReminders.value = prefs.getInt('dailyReminders') ?? 0;
  totalRestTime.value = prefs.getInt('totalRestTime') ?? 0;
  notificationsEnabled.value = prefs.getBool('notificationsEnabled') ?? true;
  reminderInterval.value = prefs.getInt('reminderInterval') ?? 20;
  userName.value = prefs.getString('userName') ?? '用户';
  eyeStrainLevel.value = prefs.getDouble('eyeStrainLevel') ?? 0.0;
}

loadSettings方法从SharedPreferences中读取保存的数据。使用??操作符提供默认值,如果SharedPreferences中没有该键,就使用默认值。这种设计确保了应用在首次运行时能够使用合理的默认值。通过这种方式,我们可以实现应用设置的持久化,使用户的设置在应用重启后仍然保留。

数据类型说明

SharedPreferences支持多种数据类型的读取操作:

  • getInt() - 读取整数值,用于存储计数器、时间间隔等整数数据
  • getBool() - 读取布尔值,用于存储开关状态、标志位等布尔数据
  • getString() - 读取字符串值,用于存储用户名、标签等文本数据
  • getDouble() - 读取浮点数值,用于存储百分比、评分等浮点数据
  • getStringList() - 读取字符串列表,用于存储多个字符串值

数据保存

在AppController中,我们提供了多个方法来保存数据。

保存整数类型数据

Future<void> updateDailyReminders(int count) async {
  dailyReminders.value = count;
  await prefs.setInt('dailyReminders', count);
}

Future<void> updateTotalRestTime(int minutes) async {
  totalRestTime.value = minutes;
  await prefs.setInt('totalRestTime', minutes);
}

Future<void> updateReminderInterval(int minutes) async {
  reminderInterval.value = minutes;
  await prefs.setInt('reminderInterval', minutes);
}

这三个方法用于保存整数类型的数据。每个方法都执行两个操作:首先更新Rx变量的值,然后将新值保存到SharedPreferences。通过async/await语法,我们可以优雅地处理异步任务。这样可以避免回调地狱。在实际应用中,异步操作对于数据库操作至关重要。这种设计确保了数据的一致性和持久化。

保存布尔类型数据

Future<void> updateNotificationsEnabled(bool enabled) async {
  notificationsEnabled.value = enabled;
  await prefs.setBool('notificationsEnabled', enabled);
}

updateNotificationsEnabled方法用于保存布尔类型的数据。这个方法控制通知功能是否启用。通过更新Rx变量,UI会自动响应式地更新。通过保存到SharedPreferences,用户的设置会被持久化。

保存字符串和浮点数类型数据

Future<void> updateUserName(String name) async {
  userName.value = name;
  await prefs.setString('userName', name);
}

Future<void> updateEyeStrainLevel(double level) async {
  eyeStrainLevel.value = level;
  await prefs.setDouble('eyeStrainLevel', level);
}

updateUserName方法保存字符串类型的用户名。updateEyeStrainLevel方法保存浮点数类型的眼睛疲劳度。这两个方法都遵循相同的模式:首先更新Rx变量,然后保存到SharedPreferences。这种设计确保了数据的一致性和持久化。

数据保存方法说明

SharedPreferences提供了多种数据类型的保存方法:

  • setInt() - 保存整数值,用于存储计数器、时间间隔等整数数据
  • setBool() - 保存布尔值,用于存储开关状态、标志位等布尔数据
  • setString() - 保存字符串值,用于存储用户名、标签等文本数据
  • setDouble() - 保存浮点数值,用于存储百分比、评分等浮点数据
  • setStringList() - 保存字符串列表,用于存储多个字符串值

数据更新流程

当用户在应用中改变设置时,我们需要更新数据。

个人资料编辑中的数据更新

ElevatedButton(
  onPressed: () {
    appController.updateUserName(_nameController.text);
    Get.snackbar(
      '成功',
      '个人资料已更新',
      snackPosition: SnackPosition.BOTTOM,
      backgroundColor: const Color(0xFF4CAF50),
      colorText: Colors.white,
    );
  },
  child: const Text('保存'),
),

当用户点击保存按钮时,我们调用appController.updateUserName()来保存用户名。这个方法会同时更新Rx变量和SharedPreferences中的数据。通过Get.snackbar显示成功提示,提高了用户体验。这种设计确保了用户的操作能够被正确保存和反馈。

数据删除

在某些情况下,我们可能需要删除保存的数据。

清空所有数据

Future<void> clearAllData() async {
  await prefs.clear();
  dailyReminders.value = 0;
  totalRestTime.value = 0;
  notificationsEnabled.value = true;
  reminderInterval.value = 20;
  userName.value = '用户';
  eyeStrainLevel.value = 0.0;
}

clearAllData方法删除所有保存的数据。首先调用prefs.clear()清空SharedPreferences中的所有数据,然后重置所有Rx变量为默认值。这种设计确保了数据的完全清空,避免了数据残留。这个方法通常在用户注销或重置应用时调用。

删除指定键的数据

Future<void> removeSetting(String key) async {
  await prefs.remove(key);
}

removeSetting方法删除指定键的数据。这个方法提供了更细粒度的数据删除控制,允许删除特定的设置而不影响其他数据。这种设计提供了灵活的数据管理能力。

数据验证

在保存数据之前,应该进行数据验证。

用户名验证

Future<void> updateUserName(String name) async {
  if (name.isEmpty) {
    Get.snackbar('错误', '用户名不能为空');
    return;
  }
  
  if (name.length > 20) {
    Get.snackbar('错误', '用户名不能超过20个字符');
    return;
  }
  
  userName.value = name;
  await prefs.setString('userName', name);
}

这个方法在保存用户名前进行了两个验证:首先检查用户名是否为空,然后检查用户名长度是否超过20个字符。通过这些验证,我们可以确保保存的数据符合要求。如果验证失败,通过Get.snackbar显示错误提示,提高了用户体验。这种设计确保了数据的有效性和应用的稳定性。

错误处理

在使用SharedPreferences时,应该处理可能的错误。

初始化错误处理

Future<void> initPreferences() async {
  try {
    prefs = await SharedPreferences.getInstance();
    loadSettings();
  } catch (e) {
    print('初始化SharedPreferences失败: $e');
    // 使用默认值
  }
}

在初始化SharedPreferences时,我们使用try-catch来捕获可能的异常。如果初始化失败,我们打印错误信息并使用默认值。这种设计确保了应用即使在SharedPreferences初始化失败时也能继续运行。

数据保存错误处理

Future<void> updateDailyReminders(int count) async {
  try {
    dailyReminders.value = count;
    await prefs.setInt('dailyReminders', count);
  } catch (e) {
    print('保存数据失败: $e');
    Get.snackbar('错误', '保存数据失败');
  }
}

在保存数据时,我们也使用try-catch来捕获异常。如果保存失败,我们打印错误信息并向用户显示错误提示。这种设计提高了应用的容错能力和用户体验。

性能优化

SharedPreferences的性能优化建议:

  1. 批量操作 - 尽量减少SharedPreferences的访问次数
  2. 异步操作 - 使用async/await避免阻塞UI
  3. 缓存数据 - 在内存中缓存常用数据,减少磁盘访问
  4. 合理设计键名 - 使用有意义的键名,便于管理

数据迁移

当应用版本更新时,可能需要迁移旧数据。

void loadSettings() {
  // 检查是否是第一次运行
  final isFirstRun = prefs.getBool('isFirstRun') ?? true;
  
  if (isFirstRun) {
    // 初始化默认值
    prefs.setBool('isFirstRun', false);
  }
  
  // 加载数据
  dailyReminders.value = prefs.getInt('dailyReminders') ?? 0;
  // ...
}

总结

SharedPreferences是Flutter中最常用的本地数据存储库。通过使用SharedPreferences,我们可以轻松地保存和加载应用的状态和用户设置。通过结合GetX的响应式编程,我们可以实现数据的自动同步和UI的自动更新。

在视力保护提醒应用中,我们使用SharedPreferences来保存用户设置、应用状态等数据。这样可以确保用户的设置在应用重启后仍然保留,提高了应用的易用性和用户体验。

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐