深入Flutter系列-Dart篇-事半功倍的操作符

132 阅读2分钟

1. 级联操作符(..

级联操作符 ..

对同一个对象进行连续调用。

对于设计模式builder(构建者模式)我们比较熟悉,在Java语言中,对同一个对象进行连续调用代码如下:

Cat cat = Cat.builder()
            .eye("blue")
            .hair("white")
            .name("mimi")
            .build();

那么在dart语言下,级联操作符跟builder模式比较类似,实现上面功能代码如下:

var cat = Cat()
            ..eye("blue")
            ..hair("white")
            ..name("mimi")
            ..build();

2. 展开操作符(......?

展开操作符(Spread Collections)

提供便捷的方法把元素插入到容器中。

支持的类型list, map, set

2.1 非空的展开操作符

var list = [1, 2, 3];
var list2 = [0, 
            ...list];

2.2 可空的展开操作符

var list = null;
var list2 = [0, 
            ...?list];

2.3 实际项目中的例子

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Row(
        children: [
          const Text("Name"),

          // Widget数组
          ...?_widgets(),
        ],
      ),
    );
  }

  // Widget数组
  List<Widget>? _widgets() {
    if (condition) {
      var vipList = <Widget>[];
      var vipIcon = Image.asset(
        "imageName",
      );
      vipList.add(const SizedBox(width: 4));
      vipList.add(vipIcon);
      return vipList;
    }
    return null;
  }
  

3. 控制流集合(Control Flow Collections)

控制流集合(Control Flow Collections)

运行在集合中使用 if 和 for 进行构建

直接看例子,现有布局如下

Widget build(BuildContext context) {
  return Row(
    children: [
      IconButton(icon: Icon(Icons.menu)),
      Expanded(child: title),
      IconButton(icon: Icon(Icons.search)),
    ],
  );
}

现在稍微做下改造,加个判断,是Android平台的话,才显示搜索按钮

按照正常写法,我们可能会这样写

Widget build(BuildContext context) {
  var buttons = <Widget>[
      IconButton(icon: Icon(Icons.menu)),
      Expanded(child: title),
  ];

  if (isAndroid) {
    buttons.add(IconButton(icon: Icon(Icons.search)));
  }

  return Row(
    children: buttons,
  );
}

上面写法阅读性稍微有点差了,这时我们可以使用控制流集合(Control Flow Collections),代码可以更加简洁明了。代码如下:

Widget build(BuildContext context) {
  return Row(
    children: [
      IconButton(icon: Icon(Icons.menu)),
      Expanded(child: title),
      if (isAndroid) IconButton(icon: Icon(Icons.search)),
    ]
  );
}

同样的 else 也是支持的。我们稍微再改造一下,不是Android平台的话,把按钮换成Icon(Icons.about),修改后代码如下:

Widget build(BuildContext context) {
  return Row(
    children: [
      IconButton(icon: Icon(Icons.menu)),
      Expanded(child: title),
      if (isAndroid)
        IconButton(icon: Icon(Icons.search))
      else
        IconButton(icon: Icon(Icons.about)),
    ]
  );
}

刚才我们聊完了if,接下来我们再聊聊for

现在我们有个需求,需要根据2个集合,把符合条件的加到数组集合中,代码如下:

var list = [
  animalA,
  animalB,
];
for (var cat in cats) {
  list.add(cat);
}
for (var dog in dogs) {
  if (isBaby(dog)) {
    list.add(dog);
  }
}
list.add(otherAnimal);

我们可以这样写控制流集合 Control Flow Collection,有更好的可读性:

var list = [
  animalA,
  animalB,
  for (var cat in cats) cat,
  for (var dog in dogs)
    if (isBaby(dog)) dog,
  otherAnimal,
];

总结

Dart 的展开操作符 (Null-aware spread、Non-null-ware spread) 和 控制流集合Control flow collections(collection if/for)

能让我们的代码更便捷、可读性更高