代码之家  ›  专栏  ›  技术社区  ›  Rémi Rousselet

如何处理不需要的小部件构建?

  •  20
  • Rémi Rousselet  · 技术社区  · 6 年前

    由于各种原因,有时 build

    我知道这是因为父母更新了。但这会造成不期望的影响。 导致问题的典型情况是使用 FutureBuilder

    @override
    Widget build(BuildContext context) {
      return FutureBuilder(
        future: httpCall(),
        builder: (context, snapshot) {
          // create some layout here
        },
      );
    }
    

    在本例中,如果 建造

    考虑到这一点,如何处理不需要的构建?有没有办法阻止生成调用?

    1 回复  |  直到 4 年前
        1
  •  0
  •   Mohsen Emami    3 年前

    这个 建造 方法的设计应该 . 这是因为许多外部因素可以触发新的小部件构建,例如:

    • 父窗口小部件重新创建了其子窗口小部件
    • 小部件所依赖的继承小部件( Class.of(context) 模式)更改

    build 触发http调用或修改任何状态 .


    这和问题有什么关系?

    您面临的问题是,您的构建方法有副作用/不纯粹,使得无关的构建调用很麻烦。

    不应该阻止构建调用,而应该使构建方法纯净,这样就可以随时调用它而不会产生影响。

    在您的示例中,您需要将小部件转换为 StatefulWidget 然后提取对 initState State :

    class Example extends StatefulWidget {
      @override
      _ExampleState createState() => _ExampleState();
    }
    
    class _ExampleState extends State<Example> {
      Future<int> future;
    
      @override
      void initState() {
        future = Future.value(42);
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return FutureBuilder(
          future: future,
          builder: (context, snapshot) {
            // create some layout here
          },
        );
      }
    }
    

    我已经知道了。我来这里是因为 真正地 想要优化重建

    也可以使小部件能够在不强制其子部件也进行构建的情况下进行重建。

    最简单的方法是用飞镖 const

    @override
    Widget build(BuildContext context) {
      return const DecoratedBox(
        decoration: BoxDecoration(),
        child: Text("Hello World"),
      );
    }
    

    多亏了这个 常数 关键字,实例 DecoratedBox 即使构建被调用数百次,也将保持不变。

    但您可以手动获得相同的结果:

    @override
    Widget build(BuildContext context) {
      final subtree = MyWidget(
        child: Text("Hello World")
      );
    
      return StreamBuilder<String>(
        stream: stream,
        initialData: "Foo",
        builder: (context, snapshot) {
          return Column(
            children: <Widget>[
              Text(snapshot.data),
              subtree,
            ],
          );
        },
      );
    }
    

    subtree 即使StreamBuilder/列执行了,也不会重建。 它之所以发生,是因为,多亏了关闭 MyWidget

    这种模式在动画中经常使用。典型用途是 AnimatedBuilder AlignTransition .

    子树