如何解决这个错误"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
所以我有一个 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