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

Flutter Web中使用Riverpod Consumer组件作为顶层组件致应用崩溃

Flutter Web + Riverpod启动崩溃问题排查与解决

问题概述

使用Flutter 3.3.5 + Riverpod实现导航与状态管理,移动端运行正常,但Web端启动时MaterialWidget直接崩溃,抛出类型错误:Expected a value of type 'ProviderListenable', but got one of type 'Null'。

核心报错点

崩溃发生在MaterialWidget的build方法中调用ref.watch(navigatorKeyProvider)和ref.watch(scaffoldMessengerKeyProvider)时,说明这两个Provider在Web环境下未被正确注册,导致ref.watch获取到null值。

代码回顾

class App extends StatelessWidget {
  const App({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ProviderScope(
      overrides: <Override>[
        mainNavigationProvider.overrideWithProvider(mainNavigationProviderImpl),
      ],
      child: const MaterialWidget(),
    );
  }
}

class MaterialWidget extends HookConsumerWidget {
  const MaterialWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    const String appTitle = 'Flutter App';

    return MaterialApp(
      title: appTitle,
      theme: lightTheme,
      darkTheme: darkTheme,
      scrollBehavior: scrollBehaviour,
      supportedLocales: AppLocalizations.supportedLocales,
      localizationsDelegates: AppLocalizations.localizationsDelegates,
      localeResolutionCallback: (locale, supportedLocales) =>
          AppLocalizations.checkLocale(locale, supportedLocales),
      debugShowCheckedModeBanner: false,
      navigatorKey: ref.watch(navigatorKeyProvider),
      scaffoldMessengerKey: ref.watch(scaffoldMessengerKeyProvider),
      home: const NavigatorWidget(),
    );
  }
}

异常信息

══╡ WIDGETS库捕获异常 ╞═══════════════════════════════════════════════════════════
构建MaterialWidget(dirty, state: _ConsumerState#7cdf4)时抛出TypeErrorImpl:
期望类型为'ProviderListenable'的值,但实际得到'Null'类型
相关错误组件:
MaterialWidget
MaterialWidget:file:///Users/chiddy/Development/flutter_app/lib/app/app.dart:16:20
lib/app/app.dart:16
调用栈:
dart-sdk/lib/internal/js_dev_runtime/private/ddc_runtime/errors.dart 266:49 throw
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 99:3 castError
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 452:10 cast
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart 635:14 as_C
dart-sdk/lib/_internal/js_dev_runtime/private/linked_hash_map.dart 171:26 putIfAbsent
packages/flutter_riverpod/src/consumer.dart 510:8 watch
packages/flutter_app/app/app.dart 38:24 build
...(省略后续栈信息)

解决步骤

1. 检查Provider定义

确保navigatorKeyProvider和scaffoldMessengerKeyProvider是正确的非空Provider类型,且未在Web环境下返回null:

// 正确定义示例
final navigatorKeyProvider = Provider<GlobalKey<NavigatorState>>((ref) {
  return GlobalKey<NavigatorState>();
});

final scaffoldMessengerKeyProvider = Provider<GlobalKey<ScaffoldMessengerState>>((ref) {
  return GlobalKey<ScaffoldMessengerState>();
});

避免在Provider内部做平台判断时遗漏Web端,比如不要出现以下错误写法:

// 错误示例:Web端返回null
final navigatorKeyProvider = Provider<GlobalKey<NavigatorState>?>((ref) {
  if (!kIsWeb) return GlobalKey<NavigatorState>();
  return null;
});

2. 确认Provider已被正确注册

如果这两个Provider有对应的override实现,确保在ProviderScope的overrides中包含Web端的有效实现,或者直接使用默认实现,不要只针对移动端做override:

return ProviderScope(
  overrides: <Override>[
    mainNavigationProvider.overrideWithProvider(mainNavigationProviderImpl),
    // 若需要override,添加这两个key的有效实现(Web端也适用)
    // navigatorKeyProvider.overrideWithValue(GlobalKey<NavigatorState>()),
    // scaffoldMessengerKeyProvider.overrideWithValue(GlobalKey<ScaffoldMessengerState>()),
  ],
  child: const MaterialWidget(),
);

3. 替换ref.watch为ref.read(可选优化)

由于navigatorKey和scaffoldMessengerKey是全局静态key,不需要监听变化,使用ref.read更合适,避免不必要的监听逻辑:

navigatorKey: ref.read(navigatorKeyProvider),
scaffoldMessengerKey: ref.read(scaffoldMessengerKeyProvider),

4. 清理Web端缓存

如果之前有构建缓存残留,执行以下命令清理后重新构建:

flutter clean
flutter pub get
flutter run -d chrome

内容的提问来源于stack exchange,提问作者peer-f

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 09:45:33