在构建期间调用setState()或markNeedsBuild

Div*_*hah 20 size listview setstate dart flutter

class MyHome extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => new MyHomePage2();
}

class MyHomePage2 extends State<MyHome> {
  List items = new List();

  buildlist(String s) {
    setState(() {
      print("entered buildlist" + s);
      List refresh = new List();
      if (s == 'button0') {
        refresh = [
          new Refreshments("Watermelon", 250),
          new Refreshments("Orange", 275),
          new Refreshments("Pine", 300),
          new Refreshments("Papaya", 225),
          new Refreshments("Apple", 250),
        ];
      } else if (s == 'button1') {
        refresh = [
          new Refreshments("Pina Colada", 250),
          new Refreshments("Bloody Mary", 275),
          new Refreshments("Long Island Ice tea", 300),
          new Refreshments("Screwdriver", 225),
          new Refreshments("Fusion Cocktail", 250),
        ];
      } else if (s == 'button2') {
        refresh = [
          new Refreshments("Virgin Pina Colada", 250),
          new Refreshments("Virgin Mary", 275),
          new Refreshments("Strawberry Flush", 300),
          new Refreshments("Mango Diver", 225),
          new Refreshments("Peach Delight", 250),
        ];
      } else {
        refresh = [
          new Refreshments("Absolute", 250),
          new Refreshments("Smirnoff", 275),
          new Refreshments("White Mischief", 300),
          new Refreshments("Romanov", 225),
          new Refreshments("Blender's Pride", 250),
        ];
      }

      for (var item in refresh) {
        items.add(new ItemsList(item));
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    var abc = MediaQuery.of(context).size;

    print(abc.width);

    var width = abc.width / 4;

    Text text = new Text("Dev");
    Text text2 = new Text("Sneha");
    Text text3 = new Text("Prashant");
    Text text4 = new Text("Vikesh");

    var pad = const EdgeInsets.all(10.0);

    Padding pad1 = new Padding(child: text, padding: pad);
    Padding pad2 = new Padding(child: text2, padding: pad);
    Padding pad3 = new Padding(child: text3, padding: pad);
    Padding pad4 = new Padding(child: text4, padding: pad);

    ListView listView = new ListView(children: <Widget>[
      new Image.asset('images/party.jpg'),
      pad1,
      pad2,
      pad3,
      pad4
    ]);

    Drawer drawer = new Drawer(child: listView);

    return new Scaffold(
      drawer: drawer,

      appBar: new AppBar(
        title: new Text('Booze Up'),
      ),
      body: new Column(children: <Widget>[
        new ListView.builder(
          scrollDirection: Axis.horizontal,
          itemCount: 4,
          itemBuilder: (BuildContext context, int index) {
            return new Column(children: <Widget>[
              new Container(
                child: new Flexible(
                    child: new FlatButton(
                  child: new Image.asset('images/party.jpg',
                      width: width, height: width),
                  onPressed: buildlist('button' + index.toString()),
                )),
                width: width,
                height: width,
              )
            ]);
          },
        ),
        new Expanded(
            child: new ListView(
          padding: new EdgeInsets.fromLTRB(10.0, 10.0, 0.0, 10.0),
          children: items,
          scrollDirection: Axis.vertical,
        )),
      ]),

      floatingActionButton: new FloatingActionButton(
        onPressed: null,
        child: new Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

class Refreshments {
  String name;
  int price;

  Refreshments(this.name, this.price);
}

class ItemsList extends StatelessWidget {
  final Refreshments refreshments;

  ItemsList(this.refreshments);

  @override
  Widget build(BuildContext context) {
    return new ListTile(
      onTap: null,
      title: new Text(refreshments.name),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

由DartPad格式化;-)

我有两个错误:

1]水平视口被赋予无限高度.水平视口被赋予了无限量的垂直空间,可以在其中展开.

2]在构建期间调用的setState()或markNeedsBuild由99488像素溢出的垂直renderflex.

请帮帮我.我正在创建这个应用程序,在每个图像上单击列表应显示如下.图像将排成一行,列表应显示在行下方.

谢谢.

Dev*_*ine 315

就我而言,我setStatebuild方法完成构建小部件的过程之前调用了该方法。

如果在方法完成之前显示 asnackBar或 an ,以及在许多其他情况下,您可能会遇到此错误。因此,在这种情况下,您应该使用回调函数,如下所示:alertDialogbuild

WidgetsBinding.instance.addPostFrameCallback((_){

  // Add Your Code here.

});
Run Code Online (Sandbox Code Playgroud)

或者你也可以使用SchedulerBindingwhich 做同样的事情:

SchedulerBinding.instance.addPostFrameCallback((_) {

  // add your code here.

  Navigator.push(
        context,
        new MaterialPageRoute(
            builder: (context) => NextPage()));
});
Run Code Online (Sandbox Code Playgroud)

  • 这应该是公认的答案。当我在“FutureBuilder”(登录成功屏幕)中创建新的“MaterialPageRoute”时,发生了此错误。 (12认同)

alf*_*eon 61

我还在构建期间设置了状态,因此,我将它推迟到下一个滴答声并且它起作用了。

之前

myFunction()
Run Code Online (Sandbox Code Playgroud)

新的

Future.delayed(Duration.zero, () async {
  myFunction();
});
Run Code Online (Sandbox Code Playgroud)

  • 最简单的方法。谢谢 (3认同)
  • 谢谢这对我有用..在我的例子中,我正在做无限gridview,我试图在底部显示加载视图,并且onBuild被调用了很多次..但是使用这个解决方案,再次感谢.. (2认同)

Gün*_*uer 57

你的代码

onPressed: buildlist('button'+index.toString()),
Run Code Online (Sandbox Code Playgroud)

执行buildlist()并将结果传递给onPressed,但这不是所需的行为.

它应该是

onPressed: () => buildlist('button'+index.toString()),
Run Code Online (Sandbox Code Playgroud)

这样一个函数(闭包)传递给onPressed,在执行时调用buildlist()

  • @hengxcv5 查找“闭包”。不同之处在于,如果将对函数的引用分配给“onPressed”,则当小部件识别出点击时可以调用该函数。问题中代码的问题是,它没有传递函数,而是立即调用该函数并将该函数的返回值分配给“onPressed”。`() =&gt; ...` 使其成为一个没有名称(闭包)的内联函数,这里没有参数,调用时执行 `buildlist(...)` (2认同)
  • 这里重要的区别是 - 传递函数本身与它的返回值。谢谢..这对我有用。另外,这里还有一个链接解释什么是函数“闭包” - 在另一个函数(父函数)内定义的函数通常可以不受限制地访问父函数的局部变量。有些语言允许这样做,Dart 就是其中之一。https://medium.com/flutter-community/understanding-lexical-closures-in-dart-flutter-863ec361a614 (2认同)

Dev*_*wal 12

问题WidgetsBinding.instance.addPostFrameCallback在于,它不是一个包罗万象的解决方案。

根据addPostFrameCallback的合同-

在此帧结束时安排回调。[...] 此回调在帧期间运行,就在持久帧回调之后 [...]。如果帧正在进行中并且尚未执行帧后回调,则在帧期间仍会执行已注册的回调。否则,注册的回调将在下一帧期间执行。

最后一行对我来说听起来像是一个交易破坏者。

该方法不适用于处理没有“当前帧”且颤振引擎空闲的情况。当然,在这种情况下,一个可以调用setState()直接,但同样,这不会永远工作-有时仅仅当前帧。


值得庆幸的是,在SchedulerBinding,还有一个解决这个小问题的方法 - SchedulerPhase

让我们建立一个更好的setState,一个不会抱怨的人。

endOfFrame与 基本相同addPostFrameCallback,除了它尝试在 安排一个新帧SchedulerPhase.idle,并且它使用 async-await 而不是回调)

Future<bool> rebuild() async {
  if (!mounted) return false;

  // if there's a current frame,
  if (SchedulerBinding.instance.schedulerPhase != SchedulerPhase.idle) {
    // wait for the end of that frame.
    await SchedulerBinding.instance.endOfFrame;
    if (!mounted) return false;
  }

  setState(() {});
  return true;
}
Run Code Online (Sandbox Code Playgroud)

这也使得更好的控制流,坦率地说,只是工作

await someTask();

if (!await rebuild()) return;

await someOtherTask();
Run Code Online (Sandbox Code Playgroud)


Eri*_*nes 8

由于一个非常愚蠢的错误,我收到了这个错误,但也许有人在这里是因为他做了完全相同的事情......

在我的代码中,我有两个类。一个班级 (B) 只是在那里为我创建一个带有 onTap 功能的特殊小部件。应该由用户点击触发的函数在另一个类 (A) 中。所以我试图将 A 类的函数传递给 B 类的构造函数,以便我可以将它分配给 onTap。

不幸的是,我没有传递我调用它们的函数。这是它的样子:

ClassB classBInstance = ClassB(...,myFunction());
Run Code Online (Sandbox Code Playgroud)

显然,这是正确的方法:

ClassB classBInstance = classB(...,myFunction);
Run Code Online (Sandbox Code Playgroud)

这解决了我的错误消息。这个错误是有道理的,因为为了让 myFunction 运行类 B 的实例,所以我的构建必须首先完成(我在调用我的函数时显示了一个快餐栏)。

希望有一天这可以帮助某人!