Flutter Provider实战:登录后如何为UserModel补充更多信息
基于ChangeNotifier实现全局用户信息管理方案
是的,你需要通过继承ChangeNotifier的类来管理用户的额外属性,这样既能存储完整的用户数据,又能避免重复发起接口请求,还能在数据更新时自动通知所有依赖组件刷新。以下是调整后的完整实现:
1. 重构UserModel(不可变数据类)
保持数据类的不可变性,避免直接修改实例属性:
class UserModel { final String uid; final int? idVendor; UserModel({required this.uid, this.idVendor}); }
2. 创建UserProvider管理用户状态
这个类负责监听Auth状态、获取用户额外信息,并在数据变化时通知组件:
class UserProvider extends ChangeNotifier { UserModel? _user; final AuthRepository _authRepo; bool _isLoading = false; UserProvider(this._authRepo) { // 监听Firebase Auth状态变化,自动同步用户信息 _authRepo.monitorAuthStateChanges.listen((userModel) { _user = userModel; if (_user != null && !_isLoading) { _fetchAdditionalUserInfo(); } notifyListeners(); }); } UserModel? get user => _user; bool get isLoading => _isLoading; Future<void> _fetchAdditionalUserInfo() async { if (_user == null) return; _isLoading = true; notifyListeners(); try { String endPoint = '${ApiEndPoints.userIdVendor}'; String url = endPoint.replaceAll('id', _user!.uid); final response = await http.get(Uri.parse(url), headers: { 'Content-Type': 'application/json; charset=utf-8', }).timeout(const Duration(seconds: 60)); if (response.statusCode == 200) { final Map<String, dynamic> jsonResponseBody = jsonDecode(response.body); final List<dynamic> data = jsonResponseBody['data']; // 创建新的UserModel实例更新数据 _user = UserModel(uid: _user!.uid, idVendor: data[0]['id_vendor']); } } on Exception catch (e) { print('获取用户额外信息失败: $e'); // 这里可根据需求添加错误提示逻辑 } finally { _isLoading = false; notifyListeners(); } } }
3. 更新Provider注册
将原来的StreamProvider替换为ChangeNotifierProvider,确保全局唯一实例:
class App extends StatelessWidget { const App({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MultiProvider( providers: [ Provider<AuthRepository>(create: (_) => AuthRepository()), ChangeNotifierProvider<UserProvider>( create: (context) => UserProvider(context.read<AuthRepository>()), ), ], child: const MaterialApp(home: AuthCheck()), ); } }
4. 页面中获取用户信息
在任意页面通过watch或select获取用户数据,只会在数据变化时刷新组件:
class AuthCheck extends StatelessWidget { const AuthCheck({Key? key}) : super(key: key); @override Widget build(BuildContext context) { final userProvider = context.watch<UserProvider>(); final user = userProvider.user; if (userProvider.isLoading) { return const Center(child: CircularProgressIndicator()); } if (user != null) { return const MainPage(); } else { return const LoginScreen(); } } } // 在MainPage中获取idVendor示例 class MainPage extends StatelessWidget { const MainPage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { final idVendor = context.select((UserProvider p) => p.user?.idVendor); return Scaffold( body: Center(child: Text('商户ID: ${idVendor ?? '未获取'}')), ); } }
关键优势
- 全局唯一实例:避免重复发起接口请求,用户信息只在Auth状态变化时获取一次
- 自动刷新:数据更新时自动通知所有依赖组件,无需手动管理状态同步
- 状态统一:所有页面共享同一用户状态,保证数据一致性
内容的提问来源于stack exchange,提问作者Rod Rodrigues
相关产品推荐
相关产品推荐

