如何解决为什么在Dart的列表定义中使用if和for?
Dart支持在创建列表期间使用“ if”和“ for”:
var nav = [
'Home','Furniture','Plants',if (promoActive) 'Outlet'
];
和:
var listOfInts = [1,2,3];
var listOfStrings = [
'#0',for (var i in listOfInts) '#$i'
];
assert(listOfStrings[1] == '#1');
这有什么意义?与创建列表并随后像在其他编程语言中一样将其附加到列表之后相比,它有什么好处?
var nav = [
'Home',];
if (promoActive) nav.add('Outlet');
解决方法
有多个因素在起作用:
- 性能
- 可读性
可读性
实现此功能的主要原因是针对ListView
/ Stack
以及所有带有children
参数的小部件。
这些小部件不支持将null
作为参数,这引起了很大的挫败感(这导致了github问题:Allow null values in child
or children[]
collections to signal that an element should not be drawn)
简而言之,问题在于窗口小部件的声明性性质意味着使用add
&co并不是真正的选择。
在集合中没有if
/ for
的情况下,我们必须编写:
List<Widget> children = [
Foo(),]
if (condition)
children.add(Bar());
return Scaffold(
body: ListView(
children: children,),);
这使得很难理解屏幕上呈现的内容,因为 build 方法现在是碎片化的
或者,我们必须写:
return Scaffold(
body: ListView(
children: [
Foo(),condition ? Bar() : null,].where((e) => e != null).toList(),);
这更具可读性,但由于缺乏比该示例更复杂的内容而难以实现
作为解决方案,我们现在可以编写:
return Scaffold(
body: ListView(
children: [
Foo(),if (condition)
Bar(),]
),);
这既可读,易写,又不易出错。
性能
此功能一个有趣的方面是,它可以提高Flutter应用程序的性能。
关于写作时要考虑的事情:
final list = <Widget>[
Foo(),];
if (condition)
list.add(Bar());
是通过使用add
,列表大小随时间变化。这意味着任何add
都可能导致List
重新分配以支持更多项目,这很昂贵。
同一问题适用于:
ListView(
children: [
Foo(),)
我们在其中有效地实例化了List
两次并对其所有项进行了两次迭代(对于where
一次,对ListView
一次)
在集合内部使用if
/ for
时不会发生这些性能问题。
编写时:
ListView(
children: [
Foo(),if (condition)
Bar(),],);
这将立即分配正确大小的List
,如果执行一次且仅执行一次,则分配。
原因是,实际上该语法等效于:
List<Widget> children;
if (condition)
children = [
Foo(),Bar(),];
else
children = [
Foo(),]
既不涉及add
也不涉及where
/ toList
我阅读了以下建议以更好地理解这一点:
Flutter API设计的一个关键目标是,尽可能 代码的文本布局反映了嵌套结构 结果用户界面。
似乎原因仅仅是出于代码易读性的目的。例如,以下代码:
var command = [
engineDartPath,frontendServer,];
for (var root in fileSystemRoots) {
command.add('--filesystem-root=$root');
}
for (var entryPointsJson in entryPointsJsonFiles) {
if (fileExists("$entryPointsJson.json")) {
command.add(entryPointsJson);
}
}
command.add(mainPath);
可以改成更简洁的形式:
var command = [
engineDartPath,for (var root in fileSystemRoots) '--filesystem-root=$root',for (var entryPointsJson in entryPointsJsonFiles)
if (fileExists("$entryPointsJson.json")) entryPointsJson,mainPath
];
文档中还有更多示例,但是简短的答案似乎仅仅是出于代码的可读性和简洁性。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。