You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 09:05:38