英文:
The following assertion was thrown building ReusableCard(dirty): setState() or markNeedsBuild() called during build
问题
我正在使用Angela Yu的Flutter构建一个BMI计算器。我的代码生成了以下错误,我不太理解。错误出现在InputPage widget
的第一行。我会非常感激任何帮助。
这是错误消息:
在构建 ReusableCard(dirty) 时抛出了以下断言:
在构建期间调用了 setState() 或 markNeedsBuild()。
还有更多错误消息如下。
```console
无法将此 InputPage widget 标记为需要构建,因为框架已经在构建小部件的过程中。只有在其祖先之一当前正在构建时,才可以在构建阶段将小部件标记为需要构建。允许发生此异常是因为框架在构建子代之前会先构建父代小部件,这意味着脏的后代将始终被构建。否则,在此构建阶段框架可能不会访问此小部件。
调用 setState() 或 markNeedsBuild() 的小部件是:InputPage
状态:_InputPageState#8c2a5
在发生错误调用时正在构建的小部件是:ReusableCard
dirty
ReusableCard
小部件的代码如下:
import 'package:flutter/material.dart';
class ReusableCard extends StatelessWidget {
final Color color;
final Widget cardChild;
final Function onPress;
const ReusableCard({
super.key,
required this.color,
this.cardChild = const SizedBox(),
required this.onPress,
});
@override
Widget build(BuildContext context) {
return Expanded(
child: GestureDetector(
onTap: onPress(),
child: Container(
margin: const EdgeInsets.all(15.0),
height: 205.0,
width: 175.0,
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(10.0),
),
child: cardChild,
),
),
);
}
}
InputPage
小部件的代码如下:
import 'package:flutter/material.dart';
import 'reusable_card.dart';
import 'icon_content.dart';
const double bottomContainerHeight = 93.0;
const activeCardColor = Color(0xFF1D1E33);
const inactiveCardColor = Color(0xFF111328);
const bottomContainerColor = Color(0xFFEB1555);
enum Gender {
male,
female,
}
class InputPage extends StatefulWidget {
const InputPage({Key? key});
@override
State<InputPage> createState() => _InputPageState();
}
class _InputPageState extends State<InputPage> {
Gender selectedGender = Gender.male;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(
'BMI CALCULATOR',
style: TextStyle(fontSize: 30.0),
),
),
body: Column(
children: [
Row(
children: [
ReusableCard(
onPress: () {
setState(() {
selectedGender = Gender.male;
});
},
color: selectedGender == Gender.male
? activeCardColor
: inactiveCardColor,
cardChild: const IconContent(icon: Icons.male, label: 'MALE'),
),
ReusableCard(
onPress: () {
setState(() {
selectedGender = Gender.female;
});
},
color: selectedGender == Gender.female
? activeCardColor
: inactiveCardColor,
cardChild: const IconContent(icon: Icons.female, label: 'FEMALE'),
),
],
),
Row(
children: [
ReusableCard(
onPress: () {},
color: activeCardColor,
),
],
),
],
),
);
}
}
英文:
I am building a BMI Calculator in Flutter by Angela Yu. My code is generating this error, I quiet do not understand. The error is somewhere in the first Row of the InputPage widget
I'll appreciate any help.
This is the error message.
The following assertion was thrown building ReusableCard(dirty):
setState() or markNeedsBuild() called during build.
Some more error message is below.
This InputPage widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was: InputPage
state: _InputPageState#8c2a5
The widget which was currently being built when the offending call was made was: ReusableCard
dirty
ReusableCard widget
import 'package:flutter/material.dart';
class ReusableCard extends StatelessWidget {
final Color color;
final Widget cardChild;
final Function onPress;
const ReusableCard({
super.key,
required this.color,
this.cardChild = const SizedBox(),
required this.onPress,
});
@override
Widget build(BuildContext context) {
return Expanded(
child: GestureDetector(
onTap: onPress(),
child: Container(
margin: const EdgeInsets.all(15.0),
height: 205.0,
width: 175.0,
decoration: BoxDecoration(
// color: Color(0xFF1D1E33),
color: color,
borderRadius: BorderRadius.circular(10.0),
),
child: cardChild,
),
),
);
}
}
InputPage widget
import 'package:flutter/material.dart';
import 'reusable_card.dart';
import 'icon_content.dart';
const double bottomContainerHeight = 93.0;
const activeCardColor = Color(0xFF1D1E33);
const inactiveCardColor = Color(0xFF111328);
const bottomContainerColor = Color(0xFFEB1555);
enum Gender {
male,
female,
}
class InputPage extends StatefulWidget {
const InputPage({Key? key}) : super(key: key);
@override
State<InputPage> createState() => _InputPageState();
}
class _InputPageState extends State<InputPage> {
Gender selectedGender = Gender.male;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(
'BMI CALCULATOR',
style: TextStyle(fontSize: 30.0),
),
),
body: Column(
children: [
Row(
children: [
ReusableCard(
onPress: () {
setState(() {
selectedGender = Gender.male;
});
},
color: selectedGender == Gender.male
? activeCardColor
: inactiveCardColor,
cardChild: const IconContent(icon: Icons.male, label: 'MALE'),
),
ReusableCard(
onPress: () {
setState(() {
selectedGender = Gender.female;
});
},
color: selectedGender == Gender.female
? activeCardColor
: inactiveCardColor,
cardChild:
const IconContent(icon: Icons.female, label: 'FEMALE'),
),
],
),
Row(
children: [
ReusableCard(
onPress: () {},
color: activeCardColor,
),
],
),
],
),
);
}
}
答案1
得分: 1
问题出在 onTap: onPress()
,它在构建时调用了该方法。
您可以在 ReusableCard
上使用 VoidCallback
而不是函数。
class ReusableCard extends StatelessWidget {
final Color color;
final Widget cardChild;
final VoidCallback onPress; // 这里
const ReusableCard({
super.key,
required this.color,
this.cardChild = const SizedBox(),
required this.onPress,
});
@override
Widget build(BuildContext context) {
return Expanded(
child: GestureDetector(
onTap: onPress, // *
child: Container(
margin: const EdgeInsets.all(15.0),
height: 205.0,
width: 175.0,
decoration: BoxDecoration(
// color: Color(0xFF1D1E33),
color: color,
borderRadius: BorderRadius.circular(10.0),
),
child: cardChild,
),
),
);
}
}
英文:
The issue is from onTap: onPress()
, it is calling the method during build time.
You can use VoidCallback
on ReusableCard
instead of function.
class ReusableCard extends StatelessWidget {
final Color color;
final Widget cardChild;
final VoidCallback onPress; // this
const ReusableCard({
super.key,
required this.color,
this.cardChild = const SizedBox(),
required this.onPress,
});
@override
Widget build(BuildContext context) {
return Expanded(
child: GestureDetector(
onTap: onPress, // *
child: Container(
margin: const EdgeInsets.all(15.0),
height: 205.0,
width: 175.0,
decoration: BoxDecoration(
// color: Color(0xFF1D1E33),
color: color,
borderRadius: BorderRadius.circular(10.0),
),
child: cardChild,
),
),
);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论