Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter - Cannot build because the frawework is already building

Tags:

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

like image 514
Alexi Coard Avatar asked Jun 11 '17 15:06

Alexi Coard


Video Answer


2 Answers

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), 
like image 145
Collin Jackson Avatar answered Sep 20 '22 23:09

Collin Jackson


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

like image 34
sheheryar501 Avatar answered Sep 21 '22 23:09

sheheryar501