分类
Flutter

Dart语言 / Flutter 中省略不省略 const 和 new 的区别

在 Flutter/Dart 开发的过程中,我们会发现,有时候调用一个Widget或者类,可以在前面加上 new ,也可以不加 new ;声明构造函数的时候,也可以加不加 const 也都不会报错。既然有两种写法,就肯定多少会有些区别。那么,区别是什么呢?

前言

在 Flutter/Dart 开发的过程中,我们会发现,有时候调用一个Widget或者类,可以在前面加上 new ,也可以不加 new ;声明构造函数的时候,也可以加不加 const 也都不会报错。既然有两种写法,就肯定多少会有些区别。

那么,区别是什么呢?

写上和不写 new 的区别

作为一个前端(声明式的UI标记语言),声明式的写法为我们提供了很直观的AST(动态语法树),使我们可以更符合人类直觉和习惯地构建一个应用。

但如果按照常规的编程语言写法,由于每个组件(Widget)其实都是一个类(class),我们在父组件中声明包含的子组件时要使用如下的写法,每个组件调用之前都要通过 new 关键字去实例化:

……
@override
Widget build(BuildContext context) {
  return new Scaffold(
    appBar: AppBar(
        title: new Text('hello'),
        centerTitle: true,
      ),
      body: new ListView(
        children: <Widget>[
          new Text('world'),
          ……
        ],
      },
  );
}
……

是不是有种不伦不类的感觉:既不像我们在HTML中清晰干净,又不像在后端编程中一样只包含逻辑。在UI标记语言和编程语言之间切换,还是挺烦的,也挺不优雅的。:(

所以在 Dart 2 版本中,将 newconst 变成了可选的。

我们只需要在组件树中,直接调用需要的组件就好了,就像一个函数一样,而不再需要多余的关键字。所以上面的代码我们可以直接重构成下面的代码:

……
@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
        title: Text('hello'),
        centerTitle: true,
      ),
      body: ListView(
        children: <Widget>[
          Text('world'),
          ……
        ],
      },
  );
}
……

你会发现,少敲了几下键盘,却带来了很大的快♂感。

所以结论是:

用不用 new ,只有 Dart 版本的区别(和手感的区别),而不会带来任何性能及其他任何东西的损耗。

const

const 关键字相对复杂一点,我们分两种情况说。

使用 const 调用组件

先贴代码:

Column(
  mainAxisAlignment: MainAxisAlignment.center,
  mainAxisSize: MainAxisSize.max,
  children: <Widget>[
    const SizedBox(height: 8.0),
  ],
)

在这种情况下,使用 const 调用,会让这个子组件在父组件的状态改变时不再被渲染,即:

除了第一次渲染外,不再触发 const 调用的这个子组件的 build 方法,节省性能,提高用户体验

其实没啥用,所以如上文提到。在 Dart 2 中,也已经变成可选的了。

const 声明构造方法

在声明一个类/组件的构造方法时,也可以使用 const。用了 const 的,叫“常量构造函数”。

如果一个类中,只包含使用 final 关键字声明的属性( 即实例化后不会再发生变化的属性 ),而且这个构造函数出了初始化这些属性之外什么都不做,那么你就可以用 const 关键字来声明构造函数。

我们知道,常量(或者编译时常量、运行时常量)存在的目的,就是为了减少性能损耗。同理,常量构造函数也是为了降低性能的损耗。

所以,如果你能够保证,在这个类中只设置 final 声明的属性,甚至没有属性。你就应该尽量使用常量构造函数。

常量构造函数对用于简单的、或者不可变的数据记录的类时非常有用。

但你也要注意,如果你不能保证这两点,请不要使用常量构造函数,不然调用你这个类的人会很难受:你只是删了一个 const, 但调用者可能会完全崩溃。

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据