如何用Riverpod实现SharedPreferences更新后Flutter UI自动刷新用户信息
使用Riverpod实现用户信息更新后的UI自动刷新
步骤1:添加依赖
在pubspec.yaml中添加所需依赖:
dependencies: flutter_riverpod: ^2.4.9 shared_preferences: ^2.2.2
执行flutter pub get安装依赖。
步骤2:创建强类型User模型
替换原来的Map存储,用强类型模型更安全易维护:
class User { final String id; final String firstName; final String lastName; final String? email; final int? phone; User({ required this.id, required this.firstName, required this.lastName, this.email, this.phone, }); factory User.fromJson(Map<String, dynamic> json) => User( id: json['_id'], firstName: json['firstName'] ?? '', lastName: json['lastName'] ?? '', email: json['email'], phone: json['phone'], ); Map<String, dynamic> toJson() => { '_id': id, 'firstName': firstName, 'lastName': lastName, 'email': email, 'phone': phone, }; }
步骤3:实现Riverpod状态管理Notifier
用AsyncNotifier处理异步加载和状态更新,自动同步SharedPreferences:
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'dart:convert'; final userProvider = AsyncNotifierProvider<UserNotifier, User?>(() => UserNotifier()); class UserNotifier extends AsyncNotifier<User?> { @override Future<User?> build() async { // 初始化时自动从SharedPreferences加载用户数据 return _loadUserFromPrefs(); } Future<User?> _loadUserFromPrefs() async { final prefs = await SharedPreferences.getInstance(); final userJson = prefs.getString('user'); return userJson != null ? User.fromJson(jsonDecode(userJson)) : null; } // 更新用户状态并同步到SharedPreferences Future<void> updateUser(User updatedUser) async { state = AsyncData(updatedUser); final prefs = await SharedPreferences.getInstance(); await prefs.setString('user', jsonEncode(updatedUser.toJson())); } }
步骤4:修改用户更新接口的代码
接口返回成功后,调用Notifier的updateUser方法更新状态:
if (response.statusCode == 200) { final Map<String, dynamic> responseBody = jsonDecode(response.body); print('User updated successfully: ${responseBody['user']}'); try { final updatedUser = User.fromJson(responseBody['user']); // 通过ref更新Riverpod状态 ref.read(userProvider.notifier).updateUser(updatedUser); } catch (e) { print('Failed to save user data: $e'); showCustomFlushbar(context, "Failed to save user data locally!"); throw Exception('Failed to save user data'); } if (context.mounted) { Navigator.pop(context); } } else { showCustomFlushbar(context, "Imeshindikana kubadili jina!"); _btnController.error(); throw Exception('Failed to update user: ${response.statusCode}'); }
注意:当前Widget需要能获取
ref,可通过继承ConsumerStatefulWidget/ConsumerWidget实现。
步骤5:重构UI实现自动刷新
用Consumer监听userProvider的状态变化,自动更新UI:
import 'package:flutter_riverpod/flutter_riverpod.dart'; // 用Consumer包裹用户信息展示区域 Consumer( builder: (context, ref, child) { final userAsync = ref.watch(userProvider); return userAsync.when( loading: () => const CircularProgressIndicator(), error: (err, _) => Text('加载失败: $err'), data: (user) { if (user == null) return const Text('未登录'); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '${user.firstName} ${user.lastName}', style: const TextStyle(fontSize: 22, fontWeight: FontWeight.w700), ), Text( user.email ?? "+${user.phone?.toString() ?? ''}", style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w400), ), ], ); }, ); }, )
步骤6:全局配置ProviderScope
在main.dart中把App包裹在ProviderScope内,确保全局能访问Riverpod:
void main() { runApp( const ProviderScope( child: MyApp(), ), ); }
额外优化:同步控制器文本
如果需要同步输入框控制器的文本,可在Consumer中监听状态变化:
ref.watch(userProvider).whenData((user) { if (user != null) { firstNameController.text = user.firstName; lastNameController.text = user.lastName; } });
内容的提问来源于stack exchange,提问作者ecnyakiha
相关产品推荐
相关产品推荐

