I am building a page, dynamicly generating some views into it. In my case the list showned will updated given the user input (used as a filter).
All was working perfectly when using a Text Widget to be dynamicly rendered, but when I tried to switch to a Column or Gridview, all went wrong And a got the folowwing error
The following assertion was thrown building ServerGrid(dirty; state: _ServerGridState#59211289()): I/flutter (14351): setState() or markNeedsBuild() called during build. I/flutter (14351): This Overlay widget cannot be marked as needing to build because the framework is already in the I/flutter (14351): process of building widgets. A widget can be marked as needing to be built during the build phase I/flutter (14351): only if one of its ancestors is currently building. This exception is allowed because the framework I/flutter (14351): builds parent widgets before children, which means a dirty descendant will always be built. I/flutter (14351): Otherwise, the framework might not visit this widget during this build phase. I/flutter (14351): The widget on which setState() or markNeedsBuild() was called was: I/flutter (14351): Overlay([LabeledGlobalKey<OverlayState>#774312152]; state: OverlayState#252339409(entries: I/flutter (14351): [OverlayEntry#727022347(opaque: false; maintainState: false), OverlayEntry#1051156104(opaque: I/flutter (14351): false; maintainState: true), OverlayEntry#280497357(opaque: false; maintainState: false), I/flutter (14351): OverlayEntry#41791024(opaque: false; maintainState: true), OverlayEntry#444321361(opaque: false; I/flutter (14351): maintainState: false), OverlayEntry#717668788(opaque: false; maintainState: true)]))
Here is the code I got so far,
ServerGrid which is where the error is thrown import 'package:flutter/material.dart';
import'package:firebase_sandbox/models/server.dart'; class ServerGrid extends StatefulWidget { ServerGrid({Key key, this.servers}) : super(key: key); final servers; @override State createState() => new _ServerGridState(); } class _ServerGridState extends State<ServerGrid> { showInfos(serv){ showDialog(context: context, child: new AlertDialog(content: new Text(serv.toString()))); } Widget buildServerTile(Server serv) { return new InkWell( onTap: showInfos(serv), child : new Column( children: [ new CircleAvatar(child : new Image.network(serv.image)), new Text( serv.name, style : new TextStyle(fontWeight: FontWeight.bold), ), new Text( serv.description, style : new TextStyle(color : Colors.grey[500]), ), ], ), ); } List<Widget> buildGrid() { var theGrid = <Widget>[]; for(Server s in widget.servers) { theGrid.add(buildServerTile(s)); } return theGrid; } @override Widget build(BuildContext context) { // return new Text("${widget.servers.toString()}"); //Working perfectly return new GridView( gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, ), children: buildGrid(), ); } }
Controller calling the view to update :
filter(value) { filteredList = _servers.where( (serv) => serv.name.contains(value) || serv.tags .where((tag) => tag.contains(value)) .length > 0 ).toList(); print(filteredList); setState(() { serverList = new ServerGrid(servers : filteredList); }); }
Been searching, but I can't figure out what is wrong when building my Gridview
You have an issue with your onTap
handler. It is trying to show the dialog immediately during your build function, which is not allowed.
onTap: showInfos(serv),
Change your handler to be a function:
onTap: () => showInfos(serv),
I have used another interesting solution. So, what is happening here is that it notifies to rebuild the UI, while UI is already building which causes the error. So, what I did to fix it was to put it inside a Future.delayed() function, and give it a small duration of say 1 milisecond. What it does is it runs notifylistener later and you won't get any problem. Obviously this is not a proper fix but can help
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With