dart 初始化Flutter小部件中的final变量-最佳实践

vmpqdwk3  于 12个月前  发布在  Flutter
关注(0)|答案(1)|浏览(122)

有时我们需要用非常量值初始化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();
  }

最后两种方式看起来都不错。哪一种方法性能更好,可以被视为最佳实践?

f45qwnt8

f45qwnt81#

实际上,2是推荐和常规的方式。为什么在你的场景中需要一个const小部件?DateTime.now()总是不同的。有什么意义?
final关键字(以及C#中的readonly)的含义是标识符应该保存一个在其生命周期内永远不会更改的运行时常量值。
在其他地方,如函数,final没有特殊的含义,因为函数运行范围。在函数中通常不需要final变量。函数的作用通常是改变某些东西,而final用于标记不可变的东西。
在上面的例子中,小部件不应该是const是有意义的,因为每当日期改变时,重新构建小部件完全有意义。
如果日期永远不会改变,那么你可以在你的小部件树中有一个硬编码的日期字符串。
不推荐使用3,不仅是因为setState,还有一个状态完整的小部件运行了一堆生命周期方法,这会产生额外的开销。

相关问题