Dart ),//此尾随逗号使生成方法的自动格式设置更方便。 ); } Widget\u buildSomeWidgets(int-val){ 打印(“${DateTime.now()}Rebuild\u buildSomeWidgets”); return const MyWidgetClass(key:key('function')); //这很糟糕,因为它每次都会重建它 //返回容器( //儿童:文本(“hi”), // ); } } 类MyWidgetClass扩展了无状态小部件{ constMyWidgetClass({Key}):超级(Key:Key); @凌驾 小部件构建(构建上下文){ 打印(“${DateTime.now()}重建MyWidgetClass$key”); 返回容器( 儿童:文本(“hi”), ); } }

Dart ),//此尾随逗号使生成方法的自动格式设置更方便。 ); } Widget\u buildSomeWidgets(int-val){ 打印(“${DateTime.now()}Rebuild\u buildSomeWidgets”); return const MyWidgetClass(key:key('function')); //这很糟糕,因为它每次都会重建它 //返回容器( //儿童:文本(“hi”), // ); } } 类MyWidgetClass扩展了无状态小部件{ constMyWidgetClass({Key}):超级(Key:Key); @凌驾 小部件构建(构建上下文){ 打印(“${DateTime.now()}重建MyWidgetClass$key”); 返回容器( 儿童:文本(“hi”), ); } },dart,flutter,Dart,Flutter,该函数的使用非常好,因为它返回一个const StatelessWidget。如果我错了,请纠正我。函数的功能和类的功能有很大区别 让我从头开始解释。每次重建小部件树时,都会重建函数返回的小部件,无论它们是否包含状态 但是,如果无状态或有状态的小部件包含的状态发生了更改,则只会在该小部件树中重建(仅重建它们) 建议将小部件提取到它们各自的类中,以提高应用程序的性能。最小化重建的小部件数量…我可以知道这是如何回答OP问题的吗?看起来我回答错了部分。我试图回答Daniel的问题,重构的无状态小部件

该函数的使用非常好,因为它返回一个
const StatelessWidget
。如果我错了,请纠正我。

函数的功能和类的功能有很大区别



让我从头开始解释。每次重建小部件树时,都会重建函数返回的小部件,无论它们是否包含状态

但是,如果无状态或有状态的小部件包含的状态发生了更改,则只会在该小部件树中重建(仅重建它们)


建议将小部件提取到它们各自的类中,以提高应用程序的性能。最小化重建的小部件数量…

我可以知道这是如何回答OP问题的吗?看起来我回答错了部分。我试图回答Daniel的问题,重构的无状态小部件构建方法仍在被调用。通过在调用重构的无状态小部件时添加
const
关键字,应该只调用一次。确定。知道了。人们可能会否决这个答案,因为它与OP问题无关。所以你应该删除它。不管怎样,选择权在你。有人能解释为什么我说的是错的吗?我的意思是,我想这是错误的,因为投了反对票。我真的同意你。我一直打算写一份更详细的差异分类,但还没有开始。请随意充实您的论点,因为我认为了解widgets v方法的优缺点很重要。@aytunch我认为您不能在任何地方使用
const
。例如,如果您有一个
无状态小部件
类,该类返回一个包含变量值的
文本
,并且该变量在某个地方发生了变化,则应重新生成
无状态小部件
,以便它可以显示不同的值,因此它不能是
常量
。我认为安全的说法是:如果安全的话,尽可能使用
const
。我一直在考虑是否自己回答这个问题。公认的答案显然是错误的,但雷米已经做了很多努力来帮助弗利特社区,因此人们可能不会像其他人那样仔细审视他的答案。从所有的投票中都可以看出这一点。人们只想要他们的“单一真相来源”。-)@这正是本主题的主题。我故意在问答中使用了“可重用”这个词。我发现这个帖子对我理解这个问题非常有用。欢迎来到Stackoverflow!我不太清楚你的回答想表达什么。您可以使用一个函数来构建小部件
shrinkHelper(){return const SizedBox.shrink();}
与在小部件树中内联使用
const SizedBox.shrink()
相同,通过使用helper函数,您可以限制一个位置的嵌套量。@DarkNeuron感谢分享。我将尝试使用帮助函数。很多单词,但这是离题演讲。。使用无状态widget优于builder函数有哪些好处?NickolaySavchenko Rémi Rousselet的更新答案显示了使用无状态小部件优于构建器函数的好处。看看他的答案的最后一部分(结论部分)@TDM我看不出有任何理由使用小部件而不是函数。如果我需要在屏幕上构建简单的块,这些块不会在其他地方重复使用;这段对话已经结束。
Widget function({ String title, VoidCallback callback }) {
  return GestureDetector(
    onTap: callback,
    child: // some widget
  );
}
class SomeWidget extends StatelessWidget {
  final VoidCallback callback;
  final String title;

  const SomeWidget({Key key, this.callback, this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
      return GestureDetector(
        onTap: callback,
        child: // some widget
      );
  }
}
Widget functionWidget({ Widget child}) {
  return Container(child: child);
}
functionWidget(
  child: functionWidget(),
);
class ClassWidget extends StatelessWidget {
  final Widget child;

  const ClassWidget({Key key, this.child}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      child: child,
    );
  }
}
new ClassWidget(
  child: new ClassWidget(),
);
Container
  Container
ClassWidget
  Container
    ClassWidget
      Container
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      ++_counter;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
            const MyWidgetClass(key: const Key('const')),
            MyWidgetClass(key: Key('non-const')),
            _buildSomeWidgets(_counter),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }

  Widget _buildSomeWidgets(int val) {
    print('${DateTime.now()} Rebuild _buildSomeWidgets');
    return const MyWidgetClass(key: Key('function'));

    // This is bad, because it would rebuild this every time
    // return Container(
    //   child: Text("hi"),
    // );
  }
}

class MyWidgetClass extends StatelessWidget {
  const MyWidgetClass({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    print('${DateTime.now()} Rebuild MyWidgetClass $key');

    return Container(
      child: Text("hi"),
    );
  }
}