有时我们需要用非常量值初始化Flutter UI小部件中的final变量(因此我们不能将其添加为默认值)。最好的方法是什么?
我认为有三种方式:
**1.在build方法中初始化。**它允许我们声明const
构造函数,但由于变量将在每次构建时重新创建-这似乎不是一个好方法。
class SomeWidget extends StatelessWidget {
const SomeWidget({super.key, this.date});
final DateTime? date;
@override
Widget build(final BuildContext context) {
final dateToShow = date ?? DateTime.now();
return...
**2.通过构造函数初始化变量。**看起来不错,但构造函数的const
修饰符丢失了。
class SomeWidget extends StatelessWidget {
SomeWidget({super.key, final DateTime? date}) : _date = date ?? DateTime.now();
final DateTime _date;
@override
Widget build(final BuildContext context) {
return...
**3.将变量初始化为StatefulWidget
状态,**看起来也没问题。我们再次使用了const
修饰符,由于没有setState()
,它不会严重影响性能。但是还有更多的样板文件,并且将创建额外的示例-State
的示例。
class SomeWidget extends StatefulWidget {
const SomeWidget({super.key, this.date});
final DateTime? date;
@override
State<SomeWidget> createState() => _SomeWidgetState();
}
class _SomeWidgetState extends State<SomeWidget> {
late final _date;
@override
void initState() {
super.initState();
_date = widget.date ?? DateTime.now();
}
最后两种方式看起来都不错。哪一种方法性能更好,可以被视为最佳实践?
1条答案
按热度按时间f45qwnt81#
实际上,2是推荐和常规的方式。为什么在你的场景中需要一个const小部件?
DateTime.now()
总是不同的。有什么意义?final
关键字(以及C#中的readonly
)的含义是标识符应该保存一个在其生命周期内永远不会更改的运行时常量值。在其他地方,如函数,
final
没有特殊的含义,因为函数运行范围。在函数中通常不需要final变量。函数的作用通常是改变某些东西,而final用于标记不可变的东西。在上面的例子中,小部件不应该是const是有意义的,因为每当日期改变时,重新构建小部件完全有意义。
如果日期永远不会改变,那么你可以在你的小部件树中有一个硬编码的日期字符串。
不推荐使用3,不仅是因为
setState
,还有一个状态完整的小部件运行了一堆生命周期方法,这会产生额外的开销。