详解Flutter(Dart)中的级联运算符(..)使用方法

发表时间: 2024-01-17 18:55

Flutter级联运算符(..)使用介绍

如果我们想对同一个对象执行一系列操作,那么我们应该使用 Cascades (. .)操作符。

使用级联运算符可以极大的减少代码量,使代码更加简洁。

class User {  late String name;  late int age;  late bool isMale;  void say(){    print("Hello, World!");  }}void main() {//不使用级联运算符  User user = User();  user.name = "Lintex";  user.age = 18;  user.isMale = true;  user.say();  //使用级联运算符  User user = User()  ..name = "Lintex"  ..age = 18  ..isMale = true  ..say();    print('${user.name} is cool!');}

通过级联操作符可以形成链式调用,上面的代码其实是这样的。第一个点可以理解成返回这个对象,第二个点再调用属性或方法。

User user = User()..name = "Lintex"..age = 18..isMale = true..say();

级联操作符属于比较特殊的操作符,在其它语言中不多见。

列表也可以使用级联运算符

List list = [];list..add(1)..add(2)..add(3)..add(4)..add(5)..remove(2);// list = [1, 3, 4, 5]

⚠️注意:级联操作后,返回值会丢失

List list = [];list..add(1)..add(2)..add(3)..add(4)..add(5)..reversed;// 期望输出 [5, 4, 3, 2, 1]// 实际输出 [1, 2, 3, 4, 5]

三个点操作符

三个点的操作符是在级联操作符的基础上扩展出来的,它的功能:用来给List赋值,相当把一个List完全复制给另外一个List。鉴于这个功能,它经常用在给List赋值的场景中。

list2=[...list];// list2 = [1, 3, 4, 5]

应用场景:

  _listView = ListView(    shrinkWrap: true,    children: [      ...list.map((e) => ListTile(title: Text(e)),).toList(),			...list2.map((e) => ListTile(title: Text(e)),).toList(),    ],  );

级联运算符在各种类型上的实践

  • 定义
  • 数组(列表List)
  • 字典(Map)
  • 字符串和StringBuffer
  • 异步方法
void main() {  // 针对自定义类的调用,中规中矩  // 需要注意的是`hello()`方法,它有返回值,但是级联调用后  // 返回值丢失了  //  String hello(String name) {  //    var value = 'hello $name';  //    print(value);  //    return value;  //	}  var model = Model()    ..hello('world')    ..sayHi('bill')    ..sayGoodbye('bill');  /*   output:    hello world   hi bill   goodbye bill   */     // 针对列表的级联  List<int> listInt = List()    ..add(0)    ..add(1)    ..add(2)    ..removeAt(1);  print(listInt); // output: [0, 2]    // 针对字典的级联  Map<String,dynamic> aMap = Map()    ..putIfAbsent('name', ()=>'bill')    ..putIfAbsent('name', ()=>'gate')    ..addAll({'sex':'male', 'age':1})    ..remove('age');  print(aMap); // output: {name: bill, sex: male}    // 一个Bug示范:对字符串的级联add,add结果均抛弃了  // 最后输出的是原字符串  String aStr = ''    ..add('line1\n')    ..add('line2\n')    ..add('line3');  print('aStr:${aStr}_${aStr.length}'); // output: aStr:_0    // 可变字符串的正确打开方式  StringBuffer aStr2 = StringBuffer()    ..write('hello ')    ..write('world');  print('aStr2:${aStr2}_${aStr2.length}'); // aStr2:hello world_11    // 对异步方法处理  // 由于异步方法的触发并需要特殊条件,所以级联调用跟普通方法一样  // 区别是异步方法仍然会异步执行,某段时间后才会执行。  class Model {    ..    Future<void> asyncSayHi(String name) {            return Future.delayed(Duration(seconds: 1), (){                    print('say hi from future $name');            });      }  }    var model1 = Model()    ..hello('world')    ..sayHi('bill')    ..sayGoodbye('bill')    ..asyncSayHi('bill');  // output:  // hello world  // hi bill  // goodbye bill  // ..(其他输出)  // say hi from future bill    // 目前的使用场景-解析json到对象  static Attachment json2Attachment(dynamic json) {    if (json == null || json is Map == false) { return null; }        var result =  Attachment()      ..id = '${json["id"]}'      ..filename = json["filename"]      ..contentId = json["contentId"]      ..contentType = json["contentType"]      ..encoding = json["encoding"]      ..estimateSize = json["estimateSize"]      ..contentLength = json["contentLength"]      ..inlined = json["inlined"]      ..type = json["type"];    return result;  }