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

Flutter报错:setState()或markNeedsBuild()在build期间调用

解决Flutter中setState() or markNeedsBuild() called during build错误

问题根源

你的代码存在两个核心问题触发了该错误:

  1. 构建过程中触发状态更新:build方法内调用了provider.initialize(),该方法内部会执行notifyListeners(),而Flutter禁止在组件构建流程中触发状态通知,否则会引发构建冲突。
  2. 构建时直接修改State成员变量:mainBody方法中直接给_heading、_name等State类的成员变量赋值,这属于在构建阶段修改状态,会打乱Flutter的构建时序。

修复方案

1. 移除build方法中的初始化调用

将provider.initialize()从build方法中移除,移到initState中执行,确保初始化逻辑只运行一次,避免在每次构建时触发状态更新。

2. 避免构建过程中直接修改State变量

通过setState方法更新本地状态,而非在构建流程中直接赋值,确保状态变更符合Flutter的生命周期规则。

3. 优化状态监听逻辑

使用Consumer监听Provider状态变化即可,无需在build中重复调用Provider.of。

修改后的完整代码

class AdressenWidget extends StatefulWidget {
  const AdressenWidget({Key? key}) : super(key: key);

  @override
  State<AdressenWidget> createState() => _AdressenWidgetState();
}

class _AdressenWidgetState extends State<AdressenWidget> {
  String _heading = '';
  String _name = '';
  String _address = '';
  String _telefon = '';
  String _email = '';
  bool _isChecked = false;

  @override
  void initState() {
    super.initState();
    _initializeAllData();
  }

  Future<void> _initializeAllData() async {
    // 仅初始化一次Provider
    final provider = locator<EAProvider>();
    await provider.initialize();
    // 初始化本地状态
    _updateLocalState(provider.addressList);
  }

  void _updateLocalState(List<Addressobject> addressList) {
    if (addressList.isNotEmpty) {
      final adress = getData(addressList, list[0]);
      setState(() {
        _heading = adress.heading;
        _name = adress.name;
        _address = adress.address;
        _telefon = adress.telefon;
        _email = adress.email;
        _isChecked = adress.isChecked;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Consumer<EAProvider>(
      builder: (context, v, child) => Container(
        margin: const EdgeInsets.fromLTRB(10, 5, 10, 5),
        padding: const EdgeInsets.fromLTRB(15, 10, 15, 10),
        decoration: auftragBox,
        child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
          Visibility(
            visible: v.expandAdrWidget,
            child: SizedBox(
              child: mainBody(v.addressList, v.isDashboard),
            ),
          )
        ]),
      ),
    );
  }

  Widget mainBody(List<Addressobject> addressList, bool isExpanded) {
    return Column(
      children: [
        IntrinsicHeight(
          child: Row(
            children: [
              SizedBox(
                height: 170,
                child: Column(
                  children: [
                    for (var i = 0; i < 6; i++)
                      InkWell(
                        onTap: () {
                          changeState(addressList, i);
                        },
                        child: const Icon(
                          Icons.location_pin,
                          color: Colors.black,
                          size: 20.0,
                        ),
                      ),
                  ],
                ),
              ),
            ],
          ),
        )
      ],
    );
  }

  void changeState(List<Addressobject> addressList, int index) {
    final adress = getData(addressList, list[index]);
    setState(() {
      _heading = adress.heading;
      _name = adress.name;
      _address = adress.address;
      _telefon = adress.telefon;
      _email = adress.email;
      _isChecked = adress.isChecked;
    });
  }
}

// Provider侧的initialize方法保持不变
// void initialize() async {
//   addressList = address_model.fromJson(addressjson).addressobject!;
//   notifyListeners();
// }

额外说明

  • 初始化逻辑移到initState的异步方法中,确保仅执行一次,避免构建循环中触发状态更新。
  • 通过_updateLocalState方法封装本地状态初始化,用setState保证状态变更符合生命周期规则。
  • 移除了build中冗余的Provider.of调用,仅保留Consumer监听状态变化。

内容的提问来源于stack exchange,提问作者Salman Akbar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 02:55:25