首页 文章详情

【Flutter】Future, async, await

老孟Flutter | 675 2021-06-09 22:00 0 0 0
UniSMS (合一短信)


Dart 为单线程语言,但它提供了异步编程的方式,Future, async, await 为异步编程的类和关键字,

Future

Future.then

异步编程最常用的场景是访问网络接口,返回数据,这里我们模拟这样的场景,2秒后返回网络数据,代码如下:

Future<String> getMyName() {
  Future.delayed(Duration(seconds: 2), () => '老孟');
}

下面将获取到的数据打印出来,

void _incrementCounter() {
  var name = getMyName();
  print('name:$name');
}

上面的用法是典型的错误用法,而且也是大部分初学者容易犯错的地方,getMyName 为 Future 方法,表示此方法为异步方法。

上面的代码打印日志如下:

flutter: name:Instance of 'Future<String>'

正确的用法如下:

void _incrementCounter() {
  getMyName().then((String value) {
    print('name:$value');
  });
}

2秒后打印日志:

flutter: name:老孟

Future.then.catchError

有这样一个Future方法:延迟1秒将字符串转换为int类型,代码如下:

Future<int> parse(String value) {
  return Future.delayed(Duration(seconds: 1), () {
    return int.parse(value);
  });
}

调用此方法:

parse("2").then((int value) {
  print('value:$value');
});

此时可以正确转换,输出日志:

flutter: value:2

如果入参为非数字,则会出现转换异常,代码如下:

parse("2a").then((int value) {
  print('value:$value');
});

运行,抛出异常:

此时,需要捕获异常并做处理,代码如下:

parse("2a").then((int value) {
  print('value:$value');
}).catchError((error){
  print('error:$error');
});

输出日志:

flutter: error:FormatException: Invalid radix-10 number (at character 1)
2a
^

Future 的异常不能使用 try..catch 捕获。

Future 可以返回任意类型的值,也可以不返回值,

Future<void> futureVoid() {
  return Future.delayed(Duration(seconds: 1), () {
    //do something
  });
}

Future.delayed

延迟处理,上面已经多次使用,延迟1秒执行:

Future.delayed(Duration(seconds: 1), () {
  //do something
});

Future.value

创建一个带返回值的 Future

Future<String> futureValue() {
  return Future.value('老孟');
}

Future.any

返回[futures]中要完成的第一个Future的结果,返回的第一个结果表示已完成,其他Future结果被抛弃。如果[futures]为空,或者没有一个Future完成,那么Future永远不会完成。

Future<String> futureAny() {
  return Future.any([
    Future.delayed(Duration(seconds: 1),()=> '1'),
    Future.delayed(Duration(seconds: 2),()=> '2'),
    Future.delayed(Duration(seconds: 3),()=> '3'),
  ]);
}

输出日志:

flutter: value:1

Future.microtask

Flutter 的 main isolate 中有2个队列:Event Queue 和 Microtask Queue ,这两个 Queue 区别是 Microtask Queue执行的优先级比Event Queue高。

Future.microtask 是向Microtask Queue添加任务,而其他Future 方法是向Event Queue中添加任务。

Future<String> futureMicrotask() {
  return Future.microtask(()=>'老孟');
}

Future.sync

表示Future中代码是同步执行的。

Future<void> futureSync() {
  return Future.sync(()=>print('Future.sync'));
}

调用:

void _incrementCounter() {
  print('Future.sync begin');
  futureSync();
  print('Future.sync end');
}

打印日志:

flutter: Future.sync begin
flutter: Future.sync
flutter: Future.sync end

Future.error

返回异常,可以通过catchError捕获。

Future<void> futureSync() {
  return Future.sync(() => print('Future.sync'));
}

调用:

futureError().catchError((error) {
  print('$error');
});

输出日志:

flutter: this is error

Future.doWhile

重复执行操作,直到返回 false。

Future<void> futureDoWhile() {
  var i = 0;
  return Future.doWhile(() {
    print('i:$i');
    return Future.value(i++ < 10);
  });
}

日志输出:

flutter: i:0
flutter: i:1
flutter: i:2
flutter: i:3
flutter: i:4
flutter: i:5
flutter: i:6
flutter: i:7
flutter: i:8
flutter: i:9
flutter: i:10

Future.forEach

遍历完所有的值或者抛出异常才变为完成状态。

Future<void> futureForEach() {
  return Future.forEach([1,2,3,5],(value){
    print('value:$value');
  });
}

日志输出:

flutter: value:1
flutter: value:2
flutter: value:3
flutter: value:5

async, await

async 和 await 关键字允许我们像写同步代码一样写异步代码,有如下异步函数:

Future<int> parse(String value) {
  return Future.delayed(Duration(seconds: 1), () {
    return int.parse(value);
  });
}

可以使用如下方法获取结果:

void _incrementCounter() {
  parse('2').then((value) => print('value:$value'));
}

也可以使用如下方法:

void _incrementCounter() async {
  var result = await parse('2');
  print('result:$result');
}

日志输出:

flutter: result:2

使用async 和 await 可读性更强。

使用 async 修饰的方法返回 Future,是异步方法。

Future<int> toInt(String value) async {
  return int.parse(value);
}

async 和 await 的异常捕获需要使用try..catcch

void _incrementCounter() async {
  try{
    await parse('1');
  }catch(e){
    
  }
}

总结

  • async 和 await 关键字可以认为是 Future 的语法糖。

  • async 和 await 关键字可以有效的解决 Future.then 嵌套问题

    void _incrementCounter() {
      fun1().then((value) {
        fun2().then((value) {
          fun3().then((value) {});
        });
      });
    }

    Future<String> fun1() {
      return Future.value('a');
    }

    Future<String> fun2() {
      return Future.value('b');
    }

    Future<String> fun3() {
      return Future.value('c');
    }

    这种地狱嵌套可读性非常差,使用async 和 await 写法:

    void _incrementCounter() async {
      var result1 = await fun1();
      var result2 = await fun2();
      var result3 = await fun3();
    }
  • Future.then 可以使用链式调用

    void _incrementCounter() async {
      fun1()
          .then((value) {})
          .then((value){});
    }


你可能还喜欢

关注「老孟Flutter」
让你每天进步一点点


good-icon 0
favorite-icon 0
收藏
回复数量: 0
    暂无评论~~
    Ctrl+Enter