跳转至

GetStorage 使用教程

GetStorage 是 GetX 官方配套的轻量级键值对存储,与 GetX 生态无缝集成,适合快速原型和轻量数据存储。


一、简介

1.1 什么是 GetStorage?

GetStorage 是 GetX 官方配套的轻量级存储: - 同步 API:无需回调,直接读写 - 无依赖:轻量级,包体积小 - GetX 集成:与 GetX Service 完美结合 - 可选加密:支持 AES 加密存储 - 全平台支持:Android/iOS/Windows/macOS/Linux

1.2 适用场景

  • 轻量配置存储
  • 与 GetX 项目配合
  • 快速原型开发
  • 用户偏好设置
  • Token/用户信息持久化

1.3 官方资源

资源 链接
Pub 页面 https://pub.dev/packages/get_storage
GetX Storage 官方文档 https://github.com/jonataslaw/get_storage
GitHub https://github.com/jonataslaw/get_storage

二、安装

# pubspec.yaml
dependencies:
  get_storage: ^2.1.1
flutter pub get

三、基础用法

3.1 初始化(App 入口)

import 'package:get_storage/get_storage.dart';

void main() async {
  await GetStorage.init();
  runApp(MyApp());
}

3.2 写入数据

final storage = GetStorage();

// 存储字符串
await storage.write('name', 'Luke');

// 存储数字
await storage.write('age', 25);

// 存储布尔值
await storage.write('isDark', true);

// 存储列表
await storage.write('tags', ['flutter', 'getx', 'dart']);

// 存储 Map
await storage.write('user', {
  'id': 1,
  'name': 'Luke',
  'email': 'luke@example.com'
});

3.3 读取数据

final storage = GetStorage();

// 读取字符串,默认值 ''
String name = storage.read('name') ?? 'default';

// 读取数字,默认值 0
int age = storage.read('age') ?? 0;

// 读取布尔值,默认值 false
bool isDark = storage.read('isDark') ?? false;

// 读取列表
List tags = storage.read('tags') ?? [];

// 读取 Map
Map? user = storage.read('user');

3.4 删除数据

final storage = GetStorage();

// 删除单个键
await storage.remove('name');

// 清空所有数据
await storage.erase();

3.5 检查键是否存在

bool exists = storage.hasData('name');

四、加密存储

4.1 初始化加密

void main() async {
  await GetStorage.init(
    encryptionCipher: HiveCipher.withPassphrase('your_secure_password'),
  );
  runApp(MyApp());
}

4.2 使用加密

// 初始化时设置加密密钥
await GetStorage.init(
  encryptionCipher: HiveAesCipher(Hive.generateSecureKey()),
);

// 所有存储自动加密
await storage.write('token', 'sensitive_data');
String token = storage.read('token');  // 自动解密

五、Service 封装

5.1 创建 StorageService

// lib/services/storage_service.dart
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';

class StorageService extends GetxService {
  late final GetStorage _box;

  Future<StorageService> init() async {
    await GetStorage.init();
    _box = GetStorage();
    return this;
  }

  // 通用读写方法
  T? read<T>(String key) => _box.read<T>(key);

  Future<void> write(String key, dynamic value) async {
    await _box.write(key, value);
  }

  Future<void> remove(String key) async => _box.remove(key);

  Future<void> clear() async => _box.erase();

  bool hasData(String key) => _box.hasData(key);

  // 业务方法封装
  bool get isDarkMode => read<bool>('isDarkMode') ?? false;

  Future<void> setDarkMode(bool value) async {
    await write('isDarkMode', value);
  }

  String? get token => read<String>('token');

  Future<void> setToken(String token) async {
    await write('token', token);
  }

  Future<void> clearToken() async => remove('token');

  Map<String, dynamic>? get userInfo => read<Map<String, dynamic>>('userInfo');

  Future<void> setUserInfo(Map<String, dynamic> info) async {
    await write('userInfo', info);
  }

  Future<void> clearUserInfo() async => remove('userInfo');
}

5.2 初始化

// main.dart
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Get.putAsync(() => StorageService().init());
  runApp(MyApp());
}

六、结合 GetX 响应式

6.1 创建响应式 Controller

// lib/controllers/theme_controller.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../services/storage_service.dart';

class ThemeController extends GetxController {
  final StorageService _storage = Get.find();

  final _isDark = false.obs;

  bool get isDark => _isDark.value;

  ThemeMode get themeMode => _isDark.value ? ThemeMode.dark : ThemeMode.light;

  @override
  void onInit() {
    super.onInit();
    _isDark.value = _storage.isDarkMode;
  }

  Future<void> toggleTheme() async {
    _isDark.value = !_isDark.value;
    await _storage.setDarkMode(_isDark.value);
    Get.changeThemeMode(themeMode);
  }
}

6.2 页面使用

class SettingsPage extends StatelessWidget {
  final ThemeController themeCtrl = Get.find();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('设置')),
      body: ListView(
        children: [
          Obx(() => SwitchListTile(
            title: Text('深色模式'),
            subtitle: Text(_isDark.value ? '已开启' : '已关闭'),
            value: themeCtrl.isDark,
            onChanged: (_) => themeCtrl.toggleTheme(),
          )),
        ],
      ),
    );
  }
}

七、实战示例:用户登录状态持久化

7.1 AuthService

// lib/services/auth_service.dart
import 'dart:convert';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';

class AuthService extends GetxService {
  late final GetStorage _box;
  static const String _tokenKey = 'auth_token';
  static const String _userKey = 'user_info';

  Future<AuthService> init() async {
    _box = GetStorage();
    return this;
  }

  bool get isLoggedIn => _box.hasData(_tokenKey);

  String? get token => _box.read<String>(_tokenKey);

  Map<String, dynamic>? get userInfo {
    final str = _box.read<String>(_userKey);
    return str != null ? jsonDecode(str) : null;
  }

  Future<void> login(String token, Map<String, dynamic> user) async {
    await _box.write(_tokenKey, token);
    await _box.write(_userKey, jsonEncode(user));
    // 通知控制器更新
    Get.find<AuthController>().updateUser(user);
  }

  Future<void> logout() async {
    await _box.remove(_tokenKey);
    await _box.remove(_userKey);
    Get.find<AuthController>().clearUser();
  }
}

// lib/controllers/auth_controller.dart
class AuthController extends GetxController {
  final RxMap<String, dynamic> user = RxMap();

  void updateUser(Map<String, dynamic> info) {
    user.value = info;
  }

  void clearUser() {
    user.clear();
  }

  bool get isLoggedIn => user.isNotEmpty;
}

7.2 初始化和服务

// main.dart
void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // 初始化 Storage 和 Auth 服务
  final storageService = await Get.putAsync(() => StorageService().init());
  Get.put(AuthController());

  // 检查登录状态
  if (storageService.token != null) {
    final userInfo = storageService.userInfo;
    if (userInfo != null) {
      Get.find<AuthController>().updateUser(userInfo);
    }
  }

  runApp(MyApp());
}

7.3 登录页面

// lib/pages/login_page.dart
class LoginPage extends StatelessWidget {
  final AuthController _authCtrl = Get.find();
  final AuthService _authService = Get.find();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('登录')),
      body: Center(
        child: ElevatedButton(
          onPressed: () async {
            // 模拟登录
            const token = 'mock_token_123';
            final user = {
              'id': 1,
              'name': 'Luke',
              'email': 'luke@example.com'
            };

            await _authService.login(token, user);

            Get.offAll(() => HomePage());
          },
          child: Text('模拟登录'),
        ),
      ),
    );
  }
}

八、完整示例:应用配置管理

// lib/services/app_settings_service.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';

class AppSettingsService extends GetxService {
  late final GetStorage _box;

  Future<AppSettingsService> init() async {
    _box = GetStorage();
    return this;
  }

  // 主题设置
  bool get isDarkMode => _box.read<bool>('darkMode') ?? false;

  ThemeMode get themeMode => isDarkMode ? ThemeMode.dark : ThemeMode.light;

  Future<void> setDarkMode(bool value) async {
    await _box.write('darkMode', value);
    Get.changeThemeMode(themeMode);
  }

  // 语言设置
  String get locale => _box.read<String>('locale') ?? 'zh_CN';

  Locale get currentLocale {
    switch (locale) {
      case 'en': return Locale('en');
      case 'ja': return Locale('ja');
      default: return Locale('zh', 'CN');
    }
  }

  Future<void> setLocale(String locale) async {
    await _box.write('locale', locale);
    Get.updateLocale(currentLocale);
  }

  // 字体大小
  double get fontScale => _box.read<double>('fontScale') ?? 1.0;

  Future<void> setFontScale(double scale) async {
    await _box.write('fontScale', scale);
  }

  // 通知设置
  bool get notificationsEnabled => _box.read<bool>('notifications') ?? true;

  Future<void> setNotifications(bool value) async {
    await _box.write('notifications', value);
  }

  // 音乐质量
  String get musicQuality => _box.read<String>('musicQuality') ?? 'high';

  Future<void> setMusicQuality(String quality) async {
    await _box.write('musicQuality', quality);
  }

  // 清空设置
  Future<void> resetSettings() async {
    await _box.erase();
  }
}

// lib/controllers/settings_controller.dart
class SettingsController extends GetxController {
  final AppSettingsService _settings = Get.find();

  bool get isDarkMode => _settings.isDarkMode;
  String get locale => _settings.locale;
  double get fontScale => _settings.fontScale;
  bool get notificationsEnabled => _settings.notificationsEnabled;
  String get musicQuality => _settings.musicQuality;

  Future<void> toggleDarkMode() async {
    await _settings.setDarkMode(!isDarkMode);
    update();
  }

  Future<void> setLocale(String locale) async {
    await _settings.setLocale(locale);
    update();
  }

  Future<void> setFontScale(double scale) async {
    await _settings.setFontScale(scale);
    update();
  }
}

九、注意事项

9.1 数据类型丢失

GetStorage 存储时会丢失 Dart 类型,读取 Map 时需要处理:

// 写入
await storage.write('data', {'count': 10});

// 读取后强制转换
Map<String, dynamic>? data = storage.read<Map<String, dynamic>>('data');
if (data != null) {
  int count = data['count'] as int;  // 需要强制转换
}

9.2 异步初始化

// 确保在 main 中初始化
void main() async {
  await GetStorage.init();  // 必须先初始化
  await Get.putAsync(() => StorageService().init());
  runApp(MyApp());
}

9.3 异常处理

try {
  final data = _box.read<Map>('key');
  if (data != null) {
    // 处理数据
  }
} catch (e) {
  // 数据可能已损坏,清除并重新初始化
  await _box.remove('key');
}

十、与其他存储方案对比

特性 GetStorage SharedPreferences Hive
复杂度 ⭐ 低 ⭐ 低 ⭐⭐ 中
性能 ⭐⭐ 中 ⭐⭐ 中 ⭐⭐⭐ 高
类型安全
加密支持
Web 支持
GetX 集成 ✅✅ 最优
学习曲线

十一、总结

GetStorage 特点:

  • GetX 官方配套:与 GetX 生态完美结合
  • 简单易用:同步 API,无需回调
  • 轻量级:包体积小
  • 可选加密:支持敏感数据存储
  • 全平台支持:所有 Flutter 平台

适用场景: - GetX 项目中的存储 - 轻量配置和偏好设置 - 快速原型开发 - Token 和用户信息持久化

不适用场景: - 复杂结构化数据(建议 drift/floor) - 超大量数据(建议 Hive/drift) - 需要复杂查询(建议 drift/sqflite)

GetStorage 是 GetX 项目中最推荐的轻量存储方案。