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

Flutter Provider跨Widget树监听报错,添加listen:false仍无效

问题解决:Provider在事件回调中使用监听方法导致的断言错误

报错信息

The following assertion was thrown while calling onSubmitted for TextInputAction.done:
Tried to listen to a value exposed with provider, from outside of the widget tree.
This is likely caused by an event handler (like a button's onPressed) that called
Provider.of without passing listen: false. To fix, write:
Provider.of(context, listen: false);
It is unsupported because may pointlessly rebuild the widget associated to the
event handler, when the widget tree doesn't care about the value.
The context used was: Boxes(dependencies: [_InheritedProviderScope<Counter?>], state:
_BoxesState#274b3)
'package:provider/src/provider.dart':
Failed assertion: line 274 pos 7: 'context.owner!.debugBuilding ||
listen == false ||
debugIsInInheritedProviderUpdate'

问题根源

你在TextField的onSubmitted事件回调里用了context.watch<Counter>(),这个方法的作用是监听Counter实例的变化并触发widget重建,但它只能在widget的build方法或构建相关的生命周期里使用。事件回调属于用户交互触发的逻辑,不在widget树的构建流程中,所以会触发这个断言错误。

你之前加的Provider.of<Counter>(context, listen: false);根本没解决问题——因为你只是获取了实例但没用到它,真正的错误来源是后面的context.watch调用。

修复方案

把事件回调里的context.watch<Counter>()替换成不监听的读取方式,两种可选:

方法1:用Provider.of指定listen: false

TextField(
    controller: _textController,
    style: const TextStyle(color: Colors.white),
    decoration: 
        const InputDecoration(
            border: 
                OutlineInputBorder(
                    borderRadius:
                        BorderRadius.all(Radius.circular(40.0)),
                ),
            labelText: "Enter here",
        ),
        onSubmitted: (value) {
            setState(() {
                _boxStorage += "- ${_textController.text}\n";
                // 替换watch为带listen: false的Provider.of
                final counter = Provider.of<Counter>(context, listen: false);
                _storage.insert(counter.count, _boxStorage);
                _saveSharedPreferences();
                _textController.clear();
            });
        }
),

方法2:用context.read(Provider提供的快捷方法,等价于listen: false)

TextField(
    controller: _textController,
    style: const TextStyle(color: Colors.white),
    decoration: 
        const InputDecoration(
            border: 
                OutlineInputBorder(
                    borderRadius:
                        BorderRadius.all(Radius.circular(40.0)),
                ),
            labelText: "Enter here",
        ),
        onSubmitted: (value) {
            setState(() {
                _boxStorage += "- ${_textController.text}\n";
                // 用read替代watch
                final counter = context.read<Counter>();
                _storage.insert(counter.count, _boxStorage);
                _saveSharedPreferences();
                _textController.clear();
            });
        }
),

关键说明

  • watch:用于widget构建时,监听状态变化自动触发重建,绝对不能在事件回调里用
  • read/Provider.of(..., listen: false):仅读取当前状态值、不监听变化,适合在事件处理、异步逻辑中使用

内容的提问来源于stack exchange,提问作者Cezary Dąbek

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 02:10:25