Flutter使用Provider实现主题切换时Home组件上方找不到Provider<ThemeChanger>报错
核心报错原因回顾
The following ProviderNotFoundException was thrown building Home(dirty, state: _HomeState#c900c):
Error: Could not find the correct Provider above this Home Widget
报错本质是Home组件的BuildContext无法向上查找到对应的ThemeNotifier Provider实例,按以下步骤逐一排查即可:
排查步骤
检查
ThemeNotifier的导入一致性
确认ChangeNotifierProvider中创建的ThemeNotifier,和Home组件中通过Provider.of<ThemeNotifier>/Consumer<ThemeNotifier>引用的类是同一个,避免相对路径和绝对路径混用、类名拼写错误导致Dart识别为两个不同类,无法匹配到Provider。检查Home组件获取Provider的写法
如果是在initState生命周期中获取Provider,必须显式指定listen: false,正确写法为:@override void initState() { super.initState(); final themeNotifier = Provider.of<ThemeNotifier>(context, listen: false); }如果是在build方法中获取,确认范型
<ThemeNotifier>没有遗漏。检查自定义路由逻辑
你当前使用自定义AppRouter生成路由,问题大概率出在此处:路由初始化逻辑放在了_MaterialAppWithThemeState的initState中,此时Provider还未完成创建,路由跳转使用的是根Context,没有包含Provider信息。
修复方案
将AppRouter的初始化逻辑移到Consumer的builder内部,使用Provider同级的Context来处理路由:
@override Widget build(BuildContext context) { return ChangeNotifierProvider( create: (_) => ThemeNotifier(), child: Consumer<ThemeNotifier>( builder: (context, ThemeNotifier notifier, child) { // 把路由初始化移到这里 AppRouter appRouter = AppRouter( routes: AppRoutes.routes, notFoundHandler: AppRoutes.routeNotFoundHandler, ); appRouter.setupRoutes(); return MaterialApp( debugShowCheckedModeBanner: false, theme: notifier.darkTheme ? dark : light, onGenerateRoute: AppRouter.router.generator, ); }, ), ); }
如果要快速验证问题根源,可以先给MaterialApp指定home: Home()参数,不走自定义路由逻辑,若此时不再报错即可确认是路由初始化时机的问题。
内容的提问来源于stack exchange,提问作者John Montana

