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