The following assertion was thrown building ReusableCard(dirty): setState() or markNeedsBuild() called during build

huangapple go评论53阅读模式
英文:

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 &#39;package:flutter/material.dart&#39;;
    
    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 &#39;package:flutter/material.dart&#39;;
import &#39;reusable_card.dart&#39;;
import &#39;icon_content.dart&#39;;

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&lt;InputPage&gt; createState() =&gt; _InputPageState();
}

class _InputPageState extends State&lt;InputPage&gt; {
  Gender selectedGender = Gender.male;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text(
          &#39;BMI CALCULATOR&#39;,
          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: &#39;MALE&#39;),
              ),
              ReusableCard(
                onPress: () {
                  setState(() {
                    selectedGender = Gender.female;
                  });
                },
                color: selectedGender == Gender.female
                    ? activeCardColor
                    : inactiveCardColor,
                cardChild:
                    const IconContent(icon: Icons.female, label: &#39;FEMALE&#39;),
              ),
            ],
          ),
          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,
        ),
      ),
    );
  }
}

huangapple
  • 本文由 发表于 2023年2月8日 22:45:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/75387438.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定