基于Riverpod实现带Secure Storage的AppState类及Provider的疑问
解决Riverpod代码生成式范式下的App状态持久化问题
核心思路
你需要用@riverpod注解生成AsyncNotifierProvider(而非简单的StateProvider),结合flutter_secure_storage实现状态的持久化与UI同步。这种方式既保留了自动生成Provider的便利性,又能处理异步加载/保存逻辑。
步骤1:依赖配置
确保pubspec.yaml中包含以下依赖:
dependencies: flutter: sdk: flutter riverpod_annotation: ^2.3.0 flutter_secure_storage: ^9.0.0 json_annotation: ^4.8.1 dev_dependencies: build_runner: ^2.4.4 riverpod_generator: ^2.3.0 json_serializable: ^6.7.0
步骤2:定义App配置模型
创建包含配置项的实体类,实现序列化/反序列化方法:
import 'package:json_annotation/json_annotation.dart'; part 'app_settings.g.dart'; @JsonSerializable() class AppSettings { final bool darkMode; AppSettings({required this.darkMode}); // 序列化方法 Map<String, dynamic> toJson() => _$AppSettingsToJson(this); // 反序列化方法,带默认值 factory AppSettings.fromJson(Map<String, dynamic> json) => _$AppSettingsFromJson(json); // 复制方法,用于更新状态 AppSettings copyWith({bool? darkMode}) { return AppSettings( darkMode: darkMode ?? this.darkMode, ); } }
步骤3:生成带持久化的Notifier Provider
用@riverpod注解创建Notifier,负责加载初始配置、更新状态、持久化数据:
import 'dart:convert'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'app_settings.dart'; part 'app_settings_provider.g.dart'; @riverpod class AppSettingsNotifier extends _$AppSettingsNotifier { final _storage = const FlutterSecureStorage(); static const _storageKey = 'app_settings'; // 初始化:从Secure Storage加载配置 @override FutureOr<AppSettings> build() async { final savedSettings = await _storage.read(key: _storageKey); if (savedSettings != null) { return AppSettings.fromJson(jsonDecode(savedSettings)); } // 无保存数据时返回默认配置 return AppSettings(darkMode: false); } // 更新深色模式并持久化 Future<void> updateDarkMode(bool newValue) async { // 先同步更新状态,触发UI重绘 state = AsyncData(state.value!.copyWith(darkMode: newValue)); // 异步保存到Secure Storage await _storage.write( key: _storageKey, value: jsonEncode(state.value!.toJson()), ); } }
步骤4:在UI中使用Provider
在设置页通过ref.watch监听状态,通过ref.read调用更新方法:
import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'app_settings_provider.dart'; class SettingsPage extends ConsumerWidget { const SettingsPage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final settingsAsync = ref.watch(appSettingsNotifierProvider); return Scaffold( appBar: AppBar(title: const Text('设置')), body: settingsAsync.when( loading: () => const Center(child: CircularProgressIndicator()), error: (err, stack) => Center(child: Text('加载失败: $err')), data: (settings) { return ListTile( title: const Text('深色模式'), trailing: Switch( value: settings.darkMode, onChanged: (value) { ref.read(appSettingsNotifierProvider.notifier).updateDarkMode(value); }, ), ); }, ), ); } }
关键说明
- 代码生成:执行
flutter pub run build_runner build生成.g.dart后缀的自动代码文件。 - AsyncValue处理:因为初始加载是异步操作,状态以
AsyncValue形式存在,必须用when方法处理加载、错误、成功三种状态。 - 扩展配置:如果需要添加更多设置项,只需在
AppSettings类中新增字段,补充序列化方法,再在Notifier中添加对应的更新函数即可。
内容的提问来源于stack exchange,提问作者Noh Kumado
相关产品推荐
相关产品推荐

