简体   繁体   中英

Flutter - setState() called during build

I'm really new with Flutter so I don't know what is happening. I was trying to make a simple view to select a card, press a button and move on to a new screen. So, anytime I select a card I need to update the class variables to reflect that change, but the emulator screen gives me an error saying setState() called during build. Other similar posts didn't give me a solution that worked for this case.

import 'package:flutter/material.dart';
import 'package:fluttertest/pick_one_image.dart';
import 'package:fluttertest/pick_two_images.dart';

class AlgorithmSelect extends StatefulWidget {
  @override
  State createState() => new AlgorithmSelectState();
}

class AlgorithmSelectState extends State<AlgorithmSelect> {
  bool isDefault = false;
  bool isRubik = false;
  bool isMeaningful = false;

  int numImages = 0;

  bool showProgressCircle = false;

  defaultSelected() {
    setState(() {
      isDefault = !isDefault;
      isRubik = false;
      isMeaningful = false;
    });
  }

  rubikSelected() {
    setState(() {
      isDefault = false;
      isRubik = !isRubik;
      isMeaningful = false;
    });
  }

  meaningfulSelected() {
    setState(() {
      isDefault = false;
      isRubik = false;
      isMeaningful = !isMeaningful;
    });
  }

  @override
  Widget build(BuildContext context) {
    var titleBorder = new BorderDirectional(top: new BorderSide(color: Colors.blue, width: 3.0), start: new BorderSide(color: Colors.blue, width: 3.0), end: new BorderSide(color: Colors.blue, width: 3.0));
    var detailBorder = new BorderDirectional(bottom: new BorderSide(color: Colors.blue, width: 3.0), start: new BorderSide(color: Colors.blue, width: 3.0), end: new BorderSide(color: Colors.blue, width: 3.0));

    var title = new Container(
        padding: EdgeInsets.all(20.0),
            child: new Column(
              crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
               new Text("Select an encryption algorithm:", textScaleFactor: 1.7,)
            ],
          ),
        );

    var defaultTitle = new Card(
      shape: isDefault ? titleBorder : null,
      margin: EdgeInsets.fromLTRB(20.0, 20.0, 20.0, 0.0),
      child: new Container(
        decoration: new BoxDecoration(color: Colors.lightBlueAccent),
        child: new Column(
          children: <Widget>[
              new Padding(padding: EdgeInsets.fromLTRB(2.5, 0.5, 2.5, 2.5),),
              new Text("Default", textScaleFactor: 1.5, style: new TextStyle(color: Colors.white,)),
          ],
      ),
      ),
    );

    var defaultDetails = new Card(
      shape: isDefault ? detailBorder : null,
      margin: EdgeInsets.fromLTRB(20.0, 0.0, 20.0, 20.0),
      child: new Container(
        decoration: new BoxDecoration(color: Colors.white),
        child: new Column(      
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
              new Padding(padding: EdgeInsets.all(10.0),),
              new Text("  • Randomized internals", textScaleFactor: 1.0, style: new TextStyle(color: Colors.black),),
              new Padding(padding: EdgeInsets.all(10.0),)
          ],
      ),
      ),
    );

    var rubikTitle = new Card(
      shape: isRubik ? titleBorder : null,
      margin: EdgeInsets.fromLTRB(20.0, 0.0, 20.0, 0.0),
      child: new Container(
        decoration: new BoxDecoration(color: Colors.teal),
        child: new Column(      
          children: <Widget>[
              new Padding(padding: EdgeInsets.fromLTRB(2.5, 0.5, 2.5, 2.5),),
              new Text("Rubik", textScaleFactor: 1.5, style: new TextStyle(color: Colors.white,)),
          ],
      ),
      ),
    );

    var rubikDetails = new Card(
      shape: isRubik ? detailBorder : null,
      margin: EdgeInsets.fromLTRB(20.0, 0.0, 20.0, 0.0),
      child: new Container(
        decoration: new BoxDecoration(color: Colors.white),
        child: new Column(      
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
              new Padding(padding: EdgeInsets.all(10.0),),
              new Text("  • Uses the Rubik's cube principle of circular shifts", textScaleFactor: 1.0, style: new TextStyle(color: Colors.black),),
          ],
      ),
      ),
    );

    var meaningfulTitle = new Card(
      shape: isMeaningful ? titleBorder : null,
      margin: EdgeInsets.fromLTRB(20.0, 20.0, 20.0, 0.0),
      child: new Container(
        decoration: new BoxDecoration(color: Colors.indigo),
        child: new Column(      
          children: <Widget>[
              new Padding(padding: EdgeInsets.fromLTRB(2.5, 0.5, 2.5, 2.5),),
              new Text("Arnold Transformation", textScaleFactor: 1.5, style: new TextStyle(color: Colors.white,)),
          ],
      ),
      ),
    );

    var meaningfulDetails = new Card(
      shape: isMeaningful ? detailBorder : null,
      margin: EdgeInsets.fromLTRB(20.0, 0.0, 20.0, 20.0),
      child: new Container(
        decoration: new BoxDecoration(color: Colors.white),
        child: new Column(      
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
              new Padding(padding: EdgeInsets.all(10.0),),
              new Text("  • Uses Arnold Transformation", textScaleFactor: 1.0, style: new TextStyle(color: Colors.black),),
          ],
      ),
      ),
    );

    return new Scaffold(
      appBar: new AppBar(
        // title: 'Select an algorithm',
        // centerTitle: true,
        backgroundColor: Colors.blue,
      ),

      body: 
      showProgressCircle ?
      new Center(
        child: new Column(

          mainAxisAlignment: MainAxisAlignment.center,

          children: <Widget>[
            CircularProgressIndicator()
          ])
          )

          :

      new ListView(
        children: [
          title,
          new GestureDetector(
            child: defaultTitle,
            onTap: this.defaultSelected,
          ),
          new GestureDetector(
            child: defaultDetails,
            onTap: this.defaultSelected,
          ),
          new GestureDetector(
            child: rubikTitle,
            onTap: this.rubikSelected,
          ),
          new GestureDetector(
            child: rubikDetails,
            onTap: this.rubikSelected,
          ),
          new GestureDetector(
            child: meaningfulTitle,
            onTap: this.meaningfulSelected,
          ),
          new GestureDetector(
            child: meaningfulDetails,
            onTap: this.meaningfulSelected,
          ),

          new Container (
            margin: EdgeInsets.fromLTRB(120, 20, 120, 20),
            child: new RaisedButton(
              child: new Text("Encrypt!", textScaleFactor: 1.5),
              padding: EdgeInsets.fromLTRB(20, 15, 20, 15),
              color: Colors.blue,
              onPressed: (isDefault || isRubik || isMeaningful) ? navigate() : null,
            )
          )
        ]
      ),
    );
  }
}

Change this line :

  onPressed: (isDefault || isRubik || isMeaningful) ? navigate() : null,

To this:

  onPressed: (isDefault || isRubik || isMeaningful) ? navigate : null,

I think it makes more sense and would read better if you expand it a bit...

from this:

onPressed: (isDefault || isRubik || isMeaningful) ? navigate() : null,

to this:

onPressed: () {
  if (isDefault || isRubik || isMeaningful) navigate();
},
enabled: (isDefault || isRubik || isMeaningful),

Passing a null value through the onPressed callback causes the button to be marked disabled. This way, it will still be disabled with the same logic.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM