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

Flutter从Provider获取值显示为Null问题求助

问题排查:Provider状态更新后获取用户ID为Null的原因

问题描述

实现了带ChangeNotifier的UserController状态管理类,登录接口调用成功后,setUser方法内可正常打印用户sId,但在Widget组件及initState中通过context.watch或Provider.of获取时,sId显示为Null。相关代码如下:

UserController代码

class UserController with ChangeNotifier {
  UserData user = UserData();

  UserData get userdata => user;

  void setUser(UserData user) {
    user = user;
    print(user.sId);
    notifyListeners();
  }

  login(data) async {
    var response = await ApiService().login(data);
    final databody = json.decode(response);
    if (databody['success']) {
      UserData authUser = UserData.fromJson(databody['data']);
      setUser(authUser);
      notifyListeners();
      return true;
    } else {
      return false;
    }
  }
}

组件中获取代码

print('id ${context.watch<UserController>().user.sId.toString()}');
print('id2 ${Provider.of<UserController>(context, listen: false).user.sId.toString()}');

Provider注册及登录逻辑

已在main.dart的MultiProvider中注册:

ChangeNotifierProvider(create: (_) => UserController()),

登录按钮点击逻辑:

showLoader(context);
UserController auth = Provider.of<UserController>(context, listen: false);

var data = {
  "userEmail": emailController.text.trim().toLowerCase(),
  "userPassword": passwordController.text.trim(),
};
auth.login(data).then((v) {
  if (v) {
    hideLoader(context);
    context.go('/homeroot');
  } else {
    hideLoader(context);
    Fluttertoast.showToast(
        backgroundColor: green,
        textColor: Colors.white,
        msg: 'Please enter correct email and password');
  }
});

原因分析

核心问题出在setUser方法中:
方法参数user和类的成员变量user重名,此时方法内的user = user是给局部参数变量赋值,并没有修改类的成员变量this.user。所以虽然方法内打印的是参数的sId(有值),但类的成员变量还是初始的空UserData实例,导致外部获取时sId为Null。

解决方案

  1. 修改setUser方法,使用this.user明确指向类的成员变量:
void setUser(UserData user) {
  this.user = user; // 用this.区分成员变量和参数
  print(this.user.sId);
  notifyListeners();
}
  1. 优化login方法,移除重复的notifyListeners()(因为setUser内已经调用):
login(data) async {
  var response = await ApiService().login(data);
  final databody = json.decode(response);
  if (databody['success']) {
    UserData authUser = UserData.fromJson(databody['data']);
    setUser(authUser);
    // 这里不需要再调用notifyListeners()
    return true;
  } else {
    return false;
  }
}

额外注意点

  • 如果在initState中获取状态,因为initState是组件初始化时执行,此时登录请求可能还未完成,状态未更新。可以在didChangeDependencies中处理,或者确保在状态更新后再访问组件。
  • 使用Provider.of(context, listen: false)时,不会监听状态变化,所以如果状态更新后需要刷新UI,建议使用context.watch或Consumer。

内容的提问来源于stack exchange,提问作者rameez khan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 23:40:29