颤抖 - 无法建造,因为frawework已经建成

时间:2017-06-11 15:51:48

标签: dart flutter

我正在构建一个页面,动态地生成一些视图。在我的情况下,显示的列表将根据用户输入(用作过滤器)进行更新。

当使用Text Widget进行动态渲染时,所有工作都非常完美,但是当我尝试切换到Column或Gridview时,一切都出错并且出现了错误

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)]))

这是我到目前为止的代码,

ServerGrid ,这是抛出错误的地方     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(),
          );
  }
}

控制器调用视图进行更新:

  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);
    });
  }

一直在搜索,但我无法弄清楚构建Gridview时出了什么问题

3 个答案:

答案 0 :(得分:19)

您的onTap处理程序存在问题。它试图在构建函数期间立即显示对话框,这是不允许的。

onTap: showInfos(serv),

将处理程序更改为函数:

onTap: () => showInfos(serv),

答案 1 :(得分:0)

您不能为fun()属性进行函数调用(例如:onTap)。

因为onTap属性仅接受一个对象。在您的代码中,showInfos(serv)不是对象,它只是一个函数调用。

在build()方法内使用函数有02种方法。

  1. 将函数调用包装在匿名函数中

例如:-

onTap: () {
showInfos(serv);
},
  1. 删除函数的括号。(通过此操作,您可以将函数调用转换为对象(回调函数)。

例如:-

onTap: showInfos,

但是在您的情况下,您必须为showInfos方法提供一些参数,以便不能删除其括号。因此,在这种情况下,您只能 仅使用01(第一个)解决方案。

更多资源:

答案 2 :(得分:0)

我使用了另一个有趣的解决方案。所以,这里发生的事情是它通知重建 UI,而 UI 已经在构建,这会导致错误。所以,我为修复它所做的是将它放在 Future.delayed() 函数中,并给它一个小的持续时间,比如 1 毫秒。 它的作用是稍后运行notifylistener,您不会遇到任何问题。 显然这不是一个正确的修复,但可以提供帮助