如何解决这个错误"setState() or markNeedsBuild() called during build."?

How to solve this error "setState() or markNeedsBuild() called during build."?

所以我有一个 table 在沼泽中,它返回一个 Future<List<..>> 和我正在尝试制作饼图的数据


class Stats extends StatefulWidget {

  @override
  _StatsState createState() => _StatsState();
}

class _StatsState extends State<Stats> {



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


  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        _buildTaskList(context)

      ],
    );
  }
}

FutureBuilder<List<Account>> _buildTaskList(BuildContext context) {


  Map<String, double> dataMap = Map();
  dataMap.putIfAbsent("SNACKS", () => Provider.of<Amount>(context,listen: false).snack_amount);
  dataMap.putIfAbsent("ENTERTAINMENT", () => Provider.of<Amount>(context,listen: false).entertainment_amount);
  dataMap.putIfAbsent("STATIONARY", () => Provider.of<Amount>(context,listen: false).stationary_amount);
  dataMap.putIfAbsent("OTHERS", () => Provider.of<Amount>(context,listen: false).others_amount);

  final dao = Provider.of<AccountDao>(context);
  return FutureBuilder(
    future: dao.getAllAccounts(),
    builder: (context, AsyncSnapshot<List<Account>> snapshot) {
      final accounts = snapshot.data ?? List();

      Provider.of<Amount>(context,listen: false).add(Calculate(accounts, Type.SNACKS), Calculate(accounts, Type.ENTERTAINMENT),
          Calculate(accounts, Type.STATIONARY), Calculate(accounts, Type.OTHERS));



      if (accounts == null) {
        return Text('No Accounts Yet');
      } else {
        return  PieChart(
          dataMap: dataMap,
        );
      }
    },
  );
}

double Calculate(List<Account> list, Type type){

  double sum=0;
  for(int i=0;i<list.length;i++){
    if(list[i].type==type){
      sum=sum+list[i].amount;
    }
  }

  return sum;
}

现在我每次 运行 都会收到错误消息

**在为 Amount 发送通知时引发了以下断言: setState() 或 markNeedsBuild() 在构建期间调用。

无法将此 _InheritedProviderScope 小部件标记为需要构建,因为框架已经在构建小部件的过程中。仅当其祖先之一当前正在构建时,才可以在构建阶段将小部件标记为需要构建。这个例外是允许的,因为框架在子部件之前构建父部件,这意味着总是会构建一个脏的后代部件。否则,框架可能不会在此构建阶段访问此小部件。 调用 setState() 或 markNeedsBuild() 的小部件是:_InheritedProviderScope 值:'Amount' 的实例 倾听价值 进行违规调用时当前正在构建的小部件是:FutureBuilder> 肮脏的 状态:_FutureBuilderState>#37282 抛出异常时,这是堆栈:

0 Element.markNeedsBuild。 (包:flutter/src/widgets/framework.dart:4167:11)

1 Element.markNeedsBuild(包:flutter/src/widgets/framework.dart:4182:6)

2 _InheritedProviderScopeElement.markNeedsNotifyDependents(包:provider/src/inherited_provider.dart:426:5)

3 ChangeNotifier.notifyListeners(包:flutter/src/foundation/change_notifier.dart:207:21)

4 Amount.add(包:moneymanager/main.dart:55:5)

... 发送通知金额为:'Amount'

的实例

**

这是金额Class

class Amount extends ChangeNotifier {

  double snack_amount=0.0;
  double entertainment_amount=0.0;
  double stationary_amount=0.0;
  double  others_amount=0.0;

  void add(double snack,double entertainment,double stationary, double others){
    snack_amount=snack;
    entertainment_amount=entertainment;
    stationary_amount=stationary;
    others_amount=others;
    notifyListeners();
  }
}

获取Future<List<..>>

的函数

```未来>getAllAccounts()=>select(accounts).get();``

编辑 我按照建议编辑了答案

return FutureBuilder(
    future: dao.getAllAccounts(),
    builder: (context, AsyncSnapshot<List<Account>> snapshot) {

      if(snapshot.connectionState==ConnectionState.done){

        final accounts = snapshot.data ?? List();




        if (accounts == null) {

          return Text('No Accounts Yet');
        } else {
          Provider.of<Amount>(context,listen: false).add(Calculate(accounts, Type.SNACKS), Calculate(accounts, Type.ENTERTAINMENT),
              Calculate(accounts, Type.STATIONARY), Calculate(accounts, Type.OTHERS));

          dataMap.putIfAbsent("SNACKS", () => Provider.of<Amount>(context,listen: false).snack_amount);
          dataMap.putIfAbsent("ENTERTAINMENT", () => Provider.of<Amount>(context,listen: false).entertainment_amount);
          dataMap.putIfAbsent("STATIONARY", () => Provider.of<Amount>(context,listen: false).stationary_amount);
          dataMap.putIfAbsent("OTHERS", () => Provider.of<Amount>(context,listen: false).others_amount);


          return  PieChart(
            dataMap: dataMap,
          );
        }

      }else if(snapshot.connectionState==ConnectionState.waiting){

        return Container();
      }else{
        return Container();
      }


    },

但还是一样的错误

The following assertion was thrown while dispatching notifications for Amount: setState() or markNeedsBuild() called during build.

此错误表示您在构建阶段调用了 setState

并且从你的日志中明确指出

只有当其中一个祖先当前正在构建时,才能在构建阶段将小部件标记为需要构建。这个例外是允许的,因为框架在子部件之前构建父部件,这意味着总是会构建一个脏的后代部件。否则,框架可能不会在此构建阶段访问此小部件

你可以实现 ConnectionState.waiting ConnectionState.done