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

Flutter Provider在变量中无法生效的问题及解决方案咨询

问题原因

当你把ChangeNotifierProvider定义为静态getter变量时,这个Provider实例会被缓存复用——第一次访问loginPage时创建实例,后续所有导航到登录页的请求都会用同一个已经创建好的Provider实例。

但Flutter的Provider机制要求:Provider必须在页面的builder回调内部被创建,这样新页面的BuildContext才能和这个Provider建立关联。复用提前创建好的Provider实例时,它的Context和新页面的Context不匹配,导致子Widget(比如LoginView)无法在自己的Context树中找到对应的Provider,从而抛出找不到Provider的错误。

而直接在push方法的builder里写Provider、或用MultiProvider能正常运行的原因是:

  • 前者每次导航都会在builder里创建新的Provider实例,和新页面的Context绑定
  • 后者的MultiProvider作为getter时,每次访问都会创建新的MultiProvider实例(内部的Provider也是每次新创建),同样能和新页面Context正确关联
解决方法

不需要改用MultiProvider,只需要把原来的静态getter变量改成静态方法,让每次调用都返回新的Provider实例即可:

修改前:

static ChangeNotifierProvider get loginPage => ChangeNotifierProvider(
        create: (_) => LoginController(),
        child: LoginView(),
      );

修改后:

static ChangeNotifierProvider loginPage() => ChangeNotifierProvider(
        create: (_) => LoginController(),
        child: LoginView(),
      );

然后在_getRoute的switch分支里调用这个方法:

builder: (_) => switch (route) {
  Routes.login => _isLoggedIn ? homePage() : loginPage(),
  // 其他路由同理改成方法调用
  _ => _notFoundPage(),
},

这样每次导航时,都会在builder回调里创建新的Provider实例,新页面的Context就能正确关联到Provider,子Widget就能正常获取到对应的Controller了。


内容的提问来源于stack exchange,提问作者JAgüero

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 13:18:09