【问题标题】:The following assertion was thrown building ItemCard(dirty): setState() or markNeedsBuild() called during build在构建 ItemCard(dirty) 时抛出了以下断言:在构建期间调用了 setState() 或 markNeedsBuild()
【发布时间】: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)
      ],
    );
  }
}

【问题讨论】:

    标签: flutter flutter-layout flutter-web flutter-animation flutter-test


    【解决方案1】:

    正在立即调用GestureDetector 中的onPress 函数。

    有两种方法可以解决问题。

    1. 通过删除() 删除对函数的调用
    2. 将 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: ...
       )
    }
    

    【讨论】:

    • 我已经尝试过您的解决方案,出现此错误消息:“参数类型 'Future' 无法分配给参数类型 'void Function()?'。”
    • @HassanWaqqaf 你到底尝试了什么?
    • 这个:"onTap: Future.delayed(Duration.zero, () async { press(); }),"
    • @HassanWaqqaf 你能在 press() 之前尝试使用await吗?在我的代码中
    • @anirudh 错误消息仍然存在..这个空安全的事情让我很紧张..
    猜你喜欢
    • 2023-02-08
    • 2021-04-19
    • 2021-11-14
    • 2019-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-15
    • 1970-01-01
    相关资源
    最近更新 更多