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

Flutter构建ConsumptionDialog时报ProviderNotFoundException错误如何解决

我是一名学生,学校没有开设移动端开发相关课程,尝试了无数次都不知道怎么修复这个错误,如果有人能帮忙我会非常感激。

错误:无法在此Builder Widget上方找到正确的Provider。出现该问题是因为你使用的BuildContext不包含你选定的Provider。

触发错误的相关组件是ConsumptionDialog,本次错误共涉及2个文件。

第一个文件:consumption_dialog.dart

class ConsumptionDialog extends StatefulWidget {
  @override
  _ConsumptionDialogState createState() => _ConsumptionDialogState();
}

class _ConsumptionDialogState extends State<ConsumptionDialog> {
  final _form = GlobalKey<FormState>();
  String? _text;

  String? _validateText(String? value) {
    if (value == null) {
      return "最低需要2000毫升";
    }

    final number = int.tryParse(value);
    if (number != null && number >= 2000) {
      return null;
    }

    return "最低需要2000毫升";
  }

  @override
  Widget build(BuildContext context) {
    final bloc = context.watch<WaterBloc>();
    return AlertDialog(
      title: Text(
        "每日饮水量",
        textAlign: TextAlign.center,
        style: TextStyle(fontWeight: FontWeight.bold),
      ),
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
      content: Form(
        key: _form,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          mainAxisSize: MainAxisSize.min,
          children: [
            Text(
              "修改每日饮水目标,单位为毫升",
              textAlign: TextAlign.center,
            ),
            SizedBox(height: 12),
            TextFormField(
              maxLength: 4,
              initialValue: bloc.state.recommendedMilliliters.toString(),
              keyboardType: TextInputType.number,
              onSaved: (value) => _text = value,
              validator: _validateText,
              autovalidateMode: AutovalidateMode.onUserInteraction,
              decoration: InputDecoration(
                hintText: "2000 毫升",
                counterText: "",
              ),
            ),
            SizedBox(height: 24),
            PrimaryButton(
              onPressed: () {
                if (_form.currentState?.validate() ?? false) {
                  _form.currentState?.save();
                  FocusScope.of(context).unfocus();
                  context.read<WaterBloc>().setRecommendedMilliliters(
                        int.parse(_text!),
                      );
                  Navigator.of(context).pop();
                }
              },
              title: "确认",
            ),
            SizedBox(height: 10),
            SecondaryButton(
              onPressed: () => Navigator.of(context).pop(),
              title: "取消",
            ),
          ],
        ),
      ),
    );
  }
}

报错位置:

Widget build(BuildContext context) {
    final bloc = context.watch<WaterBloc>();
    return AlertDialog(

第二个文件:dialog.dart

import 'package:flutter/material.dart';
import 'package:animations/animations.dart';

import 'package:stayhydratedpal/widgets/confirmation_dialog.dart';
import 'package:stayhydratedpal/widgets/consumption_dialog.dart';

Future<bool> showConfirmationDialog(
  BuildContext context, {
  required String title,
  required String content,
}) async {
  final bool confirmed = await showModal(
        context: context,
        builder: (context) {
          return ConfirmationDialog(
            title: title,
            content: content,
            onConfirm: () => Navigator.of(context).pop(true),
            onCancel: () => Navigator.of(context).pop(false),
          );
        },
      ) ??
      false;

  return confirmed;
}

Future<void> showConsumptionDialog(BuildContext context) {
  return showModal(
    context: context,
    builder: (context) => ConsumptionDialog(),
  );
}

报错位置:

Future<void> showConsumptionDialog(BuildContext context) {
  return showModal(
    context: context,
    builder: (context) => ConsumptionDialog(),
  );
}

错误原因

Flutter中通过showModal、showDialog这类方法弹出的弹窗,会被挂载到新的独立路由栈上,弹窗使用的上下文和你调用弹窗的页面上下文不在同一个组件树分支,你之前在页面层注入的WaterBloc没有覆盖到弹窗的路由树,因此找不到对应的Provider实例。

修复方案

修改dialog.dart里的showConsumptionDialog方法,将已存在的WaterBloc实例注入到弹窗的组件树中:

Future<void> showConsumptionDialog(BuildContext context) {
  return showModal(
    context: context,
    builder: (dialogContext) => BlocProvider.value(
      // 从原页面上下文获取已初始化的WaterBloc
      value: context.read<WaterBloc>(),
      child: ConsumptionDialog(),
    ),
  );
}

如果你使用的是官方Provider库而非flutter_bloc,将BlocProvider.value替换为Provider.value<WaterBloc>即可。

内容的提问来源于stack exchange,提问作者0732sta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 07:09:04