在构建 ItemCard(dirty) 时抛出了以下断言:在构建期间调用了 setState() 或 markNeedsBuild()
Posted
技术标签:
【中文标题】在构建 ItemCard(dirty) 时抛出了以下断言:在构建期间调用了 setState() 或 markNeedsBuild()【英文标题】:The following assertion was thrown building ItemCard(dirty): setState() or markNeedsBuild() called during build 【发布时间】:2021-09-09 16:40:16 【问题描述】:我是 Flutter 的新手,我正在尝试构建一个在线购物应用程序作为我的毕业设计。
每次我运行应用程序时,它都会直接进入“项目卡”方法并通过它进入“详细信息屏幕”,即使它应该只在按下导航器小部件时才会去那里。
它还将物品卡标记为脏孩子(我不太明白这意味着什么以及如何将其恢复为正常孩子)。
Error message: The following assertion was thrown building ItemCard(dirty):
setState() or markNeedsBuild() called during build.
我希望我对错误的解释足够好。这是代码, 首先是 Body 类,然后是 Item Card 类,然后是 Details Screen 类:
class Body extends StatelessWidget
@override
Widget build(BuildContext context)
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: kDefaultPaddin),
child: Text(
"Mobiles",
style: Theme.of(context)
.textTheme
.headline5!
.copyWith(fontWeight: FontWeight.bold),
),
),
Categories(),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: kDefaultPaddin),
child: GridView.builder(
itemCount: productz.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: kDefaultPaddin,
crossAxisSpacing: kDefaultPaddin,
childAspectRatio: 0.75,
),
itemBuilder: (context, index) => ItemCard(
productz: productz[index],
press: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailsScreen(
productz: productz[index],
),
)),
)),
),
),
],
);
class ItemCard extends StatelessWidget
final Productz productz;
final Function press;
const ItemCard(
Key? key,
required this.productz,
required this.press,
) : super(key: key);
@override
Widget build(BuildContext context)
return GestureDetector(
onTap: press(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
child: Container(
padding: EdgeInsets.all(kDefaultPaddin),
decoration: BoxDecoration(
color: Colors.white12,
borderRadius: BorderRadius.circular(16),
),
child: Hero(
tag: "$productz.id",
child: Image.asset(productz.item_image),
),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: kDefaultPaddin / 4),
child: Text(
// products is out demo list
productz.item_name,
style: TextStyle(color: kTextLightColor),
),
),
Text(
"\$$productz.item_price",
style: TextStyle(fontWeight: FontWeight.bold),
)
],
),
);
class DetailsScreen extends StatelessWidget
final Productz productz;
const DetailsScreen(Key? key, required this.productz) : super(key: key);
@override
Widget build(BuildContext context)
return Scaffold(
// each product have a color
backgroundColor: Colors.white12,
appBar: buildAppBar(context),
body: Body(productz: productz),
);
AppBar buildAppBar(BuildContext context)
return AppBar(
backgroundColor: Colors.white12,
elevation: 0,
leading: IconButton(
icon: Icon(Icons.arrow_back,
size: 30,
color: Colors.white,
),
onPressed: () => Navigator.pop(context),
),
actions: <Widget>[
IconButton(
icon: Icon(FontAwesomeIcons.search),
onPressed: () ,
),
IconButton(
icon: Icon(FontAwesomeIcons.shoppingCart),
onPressed: () ,
),
SizedBox(width: kDefaultPaddin / 2)
],
);
【问题讨论】:
【参考方案1】:正在立即调用GestureDetector
中的onPress
函数。
有两种方法可以解决问题。
-
通过删除
()
删除对函数的调用
将 press 函数包装在一个匿名函数中,以便稍后用户实际执行操作时调用我,这通常在需要评估变量时完成,例如在 @987654325 的 onChanged
处理程序中@ 或 TextFormField
检查下面的代码sn-ps。
方法一的例子。
@override
Widget build(BuildContext context)
return GestureDetector(
onTap: press,
child: ...
)
方法二示例:
@override
Widget build(BuildContext context)
return GestureDetector(
onTap: () => press(),
child: ...
)
【讨论】:
这应该也可以,我添加了一个 Future Delayed 实例 @Rohan 我已经尝试过你的第一个解决方案,它显示以下错误消息:“参数类型 'Function' 不能分配给参数类型 'void Function()?'。” @HassanWaqqaf 第二种解决方案或我的回答应该有效 @Rohan 您是否介意将其添加到您的答案中:“以前,press()
将结果传递给onTap
,但我们需要将function (closure)
传递给onTap
,当执行,调用press()
"
@HassanWaqqaf 是的,只需更新您的ItemCard
类变量以匹配类型,即使press
成为'void Function()?'
类型【参考方案2】:
将其推迟到下一个刻度将起作用 -
上一个
@override
Widget build(BuildContext context)
return GestureDetector(
onTap: press();
child: ...
)
改为:
@override
Widget build(BuildContext context)
return GestureDetector(
onTap: Future.delayed(Duration.zero, () async
press();
),
child: ...
)
【讨论】:
我已经尝试过您的解决方案,出现此错误消息:“参数类型 'Futureawait
吗?在我的代码中
@anirudh 错误消息仍然存在..这个空安全的事情让我很紧张..以上是关于在构建 ItemCard(dirty) 时抛出了以下断言:在构建期间调用了 setState() 或 markNeedsBuild()的主要内容,如果未能解决你的问题,请参考以下文章
颤振| ExpansionTile属性“children”在扩展时抛出了Bottous Overflowed问题