为什么 Dart 中的 const Widget 不相同?

问题描述

当我们对使用 identical() 构造函数创建的两个小部件调用 const 时,它返回 false。而在为两个非小部件对象调用相同的方法时,它返回 true

这是为什么?

void main() {

  final a = const Center(
    child: const Padding(padding: const EdgeInsets.all(8),)
  );

  final b = const Center(
    child: const Padding(padding: const EdgeInsets.all(8),)
  );

  assert(identical(a,b)); // false


  var a1 = const EdgeInsets.all(8);

  var b1 = const EdgeInsets.all(8);


  assert(identical(a1,b1)); // true

}

[ERROR:Flutter/lib/ui/ui_dart_state.cc(199)] 未处理的异常:'package:todo_improve/main.dart':断言失败:第 17 行 pos 8:'相同(a,b)':是不是真的。

解决方法

经过大量研究,这就是我发现的。

现在第一种和第二种情况之间的一个主要区别是 a 和 b 在第一种情况下是 Widget 而在第二种情况下它们不是。

现在,flutter 有一个 --track-widget-creation 标志,它在调试模式下默认启用。

这是使您看似 const 的小部件变成非 identical 的罪魁祸首。

现在这意味着当您在发布模式下运行您的应用时,您的小部件确实会是 compile time constants,因此 identical 函数确实会返回 true。

将您的代码更改为(更改是因为在发布模式下会忽略断言调用)

final a =  const Center(
  child: const Padding(padding: const EdgeInsets.all(8),)
);

final b = const Center(
  child: const Padding(padding: const EdgeInsets.all(8),)
);

print(identical(a,b));

然后尝试使用 releaseflutter run --release 模式下运行您的代码并检查您的控制台以查看将打印 true。如果您使用 flutter run 在调试中运行,您将在控制台中看到 false

有关详细信息,请参阅此 thread