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
相关产品推荐
相关产品推荐

