GetX框架里容易被忽略的那些小知识(三)

2,105 阅读6分钟

GetStorage 是 GetX 提供的一个轻量级键值存储工具,类似于 Flutter 中的 SharedPreferences,但相比之下更加简单高效。它支持同步数据读写,并且可以直接用于小型数据持久化存储。

1. GetStorage 的特点

  • 轻量级:核心库只有几 KB,非常适合处理少量数据存储需求。
  • 性能高:基于内存缓存机制,数据在内存中操作,读写速度快。
  • 无上下文依赖:不需要 BuildContext,可以在任意位置使用。
  • 实时监听:支持对数据变化的监听。
  • 数据持久化:存储的数据会自动持久化到设备的本地存储中(基于 JSON 格式)。
  • 初始化简单:无需复杂的配置,开箱即用。

2. GetStorage 的初始化

在使用 GetStorage 之前,需要先进行初始化。初始化时会创建一个默认的存储容器。

import 'package:flutter/material.dart';
import 'package:get_storage/get_storage.dart';

void main() async {
  await GetStorage.init(); // 初始化 GetStorage
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

⚠️ 注意:GetStorage.init() 是异步操作,因此需要在 main 函数中使用 await,确保初始化完成后再运行应用。

3. GetStorage 的基本用法

3.1 创建存储实例

GetStorage 默认会提供一个全局实例。

final box = GetStorage(); // 获取默认存储实例

如果需要多个存储容器,也可以自定义存储实例。

final userBox = GetStorage('UserBox'); // 创建名为 UserBox 的存储实例

3.2 数据存储

通过 write 方法将数据存储到本地。

box.write('username', 'JohnDoe'); // 存储字符串
box.write('isLoggedIn', true);    // 存储布尔值
box.write('userAge', 25);         // 存储数字
box.write('preferences', {'theme': 'dark', 'fontSize': 16}); // 存储对象

除了 write 方法以外,还有 save 方法和 cache 方法。

3.2.1 save的作用

  • save 是对 write 的封装,用于保证数据立即且持久地写入磁盘。
  • 每次调用 save 时,会直接触发磁盘操作,确保数据可以在应用重启后仍然存在。
  • 本质上,save 等价于 write,但语义上更强调持久化存储。

实现逻辑(伪代码):

Future<void> save(String key, dynamic value) async {
  await write(key, value); // 使用底层 write 方法实现存储
}

使用场景:

final storage = GetStorage();
storage.save('username', 'JohnDoe'); // 等价于 storage.write('username', 'JohnDoe')

3.2.2 cache的作用

  • cache 是对 write 的增强,额外引入了内存缓存机制。
  • 当调用 cache 时:
    1. 数据首先写入内存缓存(内存中的快速临时存储)。
    2. 随后以异步方式写入磁盘存储。
  • 这种机制提升了写入性能,特别适合频繁读写的数据。

实现逻辑(伪代码):

Future<void> cache(String key, dynamic value) async {
  memoryCache[key] = value; // 将数据存入内存缓存
  write(key, value);        // 异步写入磁盘(调用底层 write 方法)
}

使用场景:

final storage = GetStorage();
storage.cache('username', 'JohnDoe'); // 优化性能的存储方式

⚠️ 注意:尽管 cache 主要强调内存缓存的优化,它最终还是会将数据异步写入磁盘,因此应用重启后仍然可以通过 read 方法读取到这些数据。

final storage = GetStorage();

// 重启后再次读取
print(storage.read('username')); // 输出: JohnDoe

3.3 数据读取

通过 read 方法读取数据。

String username = box.read('username') ?? 'Guest';
bool isLoggedIn = box.read('isLoggedIn') ?? false;
Map<String, dynamic> preferences = box.read('preferences') ?? {};

3.4 数据删除

通过 remove 方法删除某个键值对。

box.remove('username'); // 删除键为 'username' 的数据

删除所有数据。

box.erase(); // 清空存储容器

4. GetStorage 的存储位置

在 GetStorage 中,保存的数据存储在设备的文件系统中,其具体位置依赖于运行的操作系统和平台。

4.1 Android 平台

在 Android 平台上,GetStorage 使用了应用的内部存储目录,数据通常存储在以下位置:

/data/data/<your_app_package_name>/files/get_storage/

特点:

  • 私有存储: 该路径属于应用的沙箱环境,其他应用无法访问这些文件。
  • 安全性: 数据默认只对当前应用可见,不需要额外权限。
  • 删除情况: 当用户卸载应用时,此目录会被系统自动清理。

4.2 iOS 平台

在 iOS 平台上,GetStorage 数据存储在应用的沙盒目录下:

<your_app_sandbox>/Documents/get_storage/

特点:

  • 沙盒机制: 数据被存储在 Documents 文件夹下,该文件夹对当前应用是私有的。
  • iCloud 同步: 由于存储在 Documents 文件夹,默认可能会被 iCloud 自动备份(如果启用了备份的话)。
  • 删除情况: 应用被卸载时,此目录会被系统清理。

5. GetStorage 的进阶功能

5.1 数据监听

GetStorage 支持对指定键的变化进行监听。每当数据发生变化时,回调函数会被触发。

box.listen(() {
  print('数据发生变化:${box.read('username')}');
});

// 或监听特定键
box.listenKey('username', (value) {
  print('用户名更新为:$value');
});

5.2 数据同步

GetStorage 的所有操作都是同步的,存储操作立即生效,因此不需要等待异步操作完成。

5.3 自定义储存位置

默认情况下,GetStorage 会在设备的默认存储路径下创建一个 JSON 文件。如果需要自定义存储路径,可以在初始化时指定。

await GetStorage.init('UserBox', 'your/custom/path');

6. 使用场景

6.1 保存用户登录状态

final box = GetStorage();

// 保存登录状态
void login() {
  box.write('isLoggedIn', true);
}

// 检查用户是否已登录
bool checkLoginStatus() {
  return box.read('isLoggedIn') ?? false;
}

6.2 实现主题切换并保存用户选择

final box = GetStorage();

// 切换主题并保存
void toggleTheme() {
  bool isDarkMode = box.read('isDarkMode') ?? false;
  box.write('isDarkMode', !isDarkMode);
  Get.changeTheme(isDarkMode ? ThemeData.light() : ThemeData.dark());
}

// 初始化时加载用户选择的主题
void loadTheme() {
  bool isDarkMode = box.read('isDarkMode') ?? false;
  Get.changeTheme(isDarkMode ? ThemeData.dark() : ThemeData.light());
}

6.3 保存用户设置和偏好

final box = GetStorage();

// 保存用户偏好
void savePreferences() {
  box.write('preferences', {
    'theme': 'dark',
    'fontSize': 16,
    'notificationsEnabled': true,
  });
}

// 读取用户偏好
Map<String, dynamic> loadPreferences() {
  return box.read('preferences') ?? {};
}

6.4 本地缓存接口数据

一般情况下,可以通过 GetStorage 缓存接口数据,减少重复请求。

Future<Map<String, dynamic>> fetchData() async {
  final cachedData = box.read('apiData');
  if (cachedData != null) {
    return cachedData; // 返回缓存数据
  }

  // 模拟从 API 获取数据
  final apiData = {'id': 1, 'name': 'GetX'};
  box.write('apiData', apiData); // 缓存数据
  return apiData;
}

7. 与其他常用的存储工具的对比

特性GetStorageSharedPreferencesHive
异步支持同步读写异步异步
数据格式JSON 格式键值对自定义二进制格式
性能高性能中等高性能
监听支持支持不支持支持
自定义存储位置支持不支持支持
使用场景小型存储小型存储大量结构化数据存储

8. 注意事项

  1. 非大型存储解决方案:GetStorage 适合用于小型数据存储(如用户偏好、状态标志等)。如果需要存储大量或复杂结构的数据,建议使用 Hive 或 SQLite。

  2. 默认存储位置:GetStorage 默认会将数据存储在应用的私有存储路径中,删除应用时会一并清除。

  3. 加密存储:GetStorage 本身不提供加密功能。如果需要安全存储敏感数据,建议结合加密库(如 encrypt)使用。

9. 总结

GetStorage 是一个轻量级、快速、易用的存储工具,特别适合以下场景:

  • 存储用户偏好和设置(如主题、语言选择)。
  • 缓存小型接口数据。
  • 保存应用状态(如登录状态、Token 等)。
  • 实现数据变化监听。

通过简单的 API 和高效的性能,GetStorage 成为小型数据存储的优秀选择,与 GetX 框架的其他模块无缝集成,为使用者带来了极大的便利。