IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 【flutter】dart中future的使用 -> 正文阅读

[移动开发]【flutter】dart中future的使用

背景

编程中的代码执行,通常分为同步与异步两种。简单说,同步就是按照代码的编写顺序,从上到下依次执行,这也是最简单的我们最常接触的一种形式。但是同步代码的缺点也显而易见,如果其中某一行或几行代码非常耗时,那么就会阻塞,使得后面的代码不能被立刻执行。

异步的出现正是为了解决这种问题,它可以使某部分耗时代码不在当前这条执行线路上立刻执行,那究竟怎么执行呢?最常见的一种方案是使用多线程,也就相当于开辟另一条执行线,然后让耗时代码在另一条执行线上运行,这样两条执行线并列,耗时代码自然也就不能阻塞主执行线上的代码了。

多线程虽然好用,但是在大量并发时,仍然存在两个较大的缺陷,一个是开辟线程比较耗费资源,线程开多了机器吃不消,另一个则是线程的锁问题,多个线程操作共享内存时需要加锁,复杂情况下的锁竞争不仅会降低性能,还可能造成死锁。因此又出现了基于事件的异步模型。简单说就是在某个单线程中存在一个事件循环和一个事件队列,事件循环不断的从事件队列中取出事件来执行,这里的事件就好比是一段代码,每当遇到耗时的事件时,事件循环不会停下来等待结果,它会跳过耗时事件,继续执行其后的事件。当不耗时的事件都完成了,再来查看耗时事件的结果。因此,耗时事件不会阻塞整个事件循环,这让它后面的事件也会有机会得到执行。

我们很容易发现,这种基于事件的异步模型,只适合I/O密集型的耗时操作,因为I/O耗时操作,往往是把时间浪费在等待对方传送数据或者返回结果,因此这种异步模型往往用于网络服务器并发。如果是计算密集型的操作,则应当尽可能利用处理器的多核,实现并行计算。
在这里插入图片描述

于处理异步操作,异步处理成功了就执行成功的操作,异步处理失败就捕获错误或者停止后续操作,一个Future只会对应一个结果,要么成功,要么失败。

Future的所有API的返回值仍然是一个Future对象,所以可以很方便的进行链式调用。

Future.then

模拟延时操作
then中接收异步结果并打印结果

Future.delayed(new Duration(seconds: 2),(){
   return "hi world!";
}).then((data){
   print(data);
});

Future.catchError

如果异步任务发生错误,可以在catchError中捕获错误

Future.delayed(new Duration(seconds: 2),(){
   //return "hi world!";
   throw AssertionError("Error");
}).then((data){
   //执行成功会走到这里
   print("success");
}).catchError((e){
   //执行失败会走到这里
   print(e);
});

then 接收结果,catchError铺货异常,但并非只有catchError回调才能铺货错误,then方法还有一个可选参数onError,也可以铺货异常

Future.whenComplete

无论异步任务执行成功或失败都需要做一些事时,

  1. 可以分别在 then 或 catchError中关闭以下对话框
  2. 可以使用Future的whenComplete回调
Future.delayed(new Duration(seconds: 2),(){
   //return "hi world!";
   throw AssertionError("Error");
}).then((data){
   //执行成功会走到这里
   print(data);
}).catchError((e){
   //执行失败会走到这里
   print(e);
}).whenComplete((){
   //无论成功或失败都会走到这里
});

Future.wait

如果需要等待多个异步任务都执行结束后做某些操作,可以使用Future.wait,它接受一个Future数组参数,

  • 只有数组中所有的Future都执行成功后,才会触发then的成功回调,
  • 只要有一个Future执行失败,就会触发错误回调
Future.wait([
  // 2秒后返回结果
  Future.delayed(new Duration(seconds: 2), () {
    return "hello";
  }),
  // 4秒后返回结果
  Future.delayed(new Duration(seconds: 4), () {
    return " world";
  })
]).then((results){
  print(results[0]+results[1]);
}).catchError((e){
  print(e);
});

Future.delayed

Future.delay延迟两秒后执行第二个参数里面的内容,返回一个Future对象,执行then后面的内容,then里面方法的参数为delayed第二个参数方法返回的内容,也就是"Hello World!"

Future.delayed(new Duration(seconds: 2),(){
  return "Hello World!";
}).then((data){
  print(data);
});

由于then方法返回还是一个Future,所以可以用链式调用一直拼接then执行相关代码

Future.delayed(new Duration(seconds: 2),(){
  return 'Hello';
}).then((data){
  return data + ' World';
}).then((data){
  return data + ' and';
}).then((data){
  return data + ' 野猿新一!';
}).then((data){
  print(data);
}).catchError((e){
  print(e);
});

运行结果如下

Hello World and 野猿新一!

onError

其实不止catchError方法可以捕获异常,在then方法中还提供了一个可选参数onError,当发生异常的时候,会走到onError参数所传入的方法

Future.delayed(new Duration(seconds: 2), () {
    // 2秒后抛出一个异常
    throw AssertionError("Error");
}).then((data) {
    // 正常执行后回调该方法
    print("success");
}, onError: (e) {
    // 发生异常后回调该方法
    print(e);
});

我们再来看下,若同时设置then方法的onError参数和调用catchError方法,当发生异常时程序会走到哪

Future.delayed(new Duration(seconds: 2), () {
    throw AssertionError("Error");
}).then((data) {
    print("success");
}, onError: (e) {
    print('onError ' + e.toString());
}).catchError((e){
   print('catchError ' + e.toString());
});

输出结果如下

onError Assertion failed

可以看到当同时设置onError和catchError的时候,当发生异常时,程序只会走onError,而不会走到catchError

当然实际写代码的也无需两个都写,这里我比较推荐写catchError,链式调用这样的代码层次比较清晰

Futere <T>

future是一个Futere的一个泛型对象,表示一个异步操作的结果是T类型。如果这个结果不是可以直接使用,可以使用Future。 当调用返回future的函数时,会发生2件事。

函数队列开始执行,结束的时候返回一个Future对象.

当这个操作结束的时候,这个Future对象会返回一个值或者error.

当需要依赖Future去编码时,可以有两个选择

使用asyn和await

使用Future的API

 //视频模块的接口
  Future<Vediomessage> getVedioMessage() async {
    int courseId = Store.read<CourseItemInfo>(context).info.courseId;
    Vediomessage data;
    var response = await FHttp.get('/S9?cou_id=${courseId}');
    var model = Vediomessage.fromJson(response);
    if (model.code == "200") {
      print(200);
      data = model;
    }
    return data;
  }
import 'dart:convert';

class Vediomessage {
  String msg;
  String code;
  List<String> data;

  Vediomessage({this.msg, this.code, this.data});

  Vediomessage.fromMap(Map<String, dynamic> json) {
    msg = json['msg'];
    code = json['code'];
    data = json['data'].cast<String>();
  }

  Map<String, dynamic> toMap() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['msg'] = this.msg;
    data['code'] = this.code;
    data['data'] = this.data;
    return data;
  }
  String toJson() =>
      json.encode(toMap()); //将一个json格式的string 转化成一个Map<String,dynamic>类型的Map

  static Vediomessage fromJson(source) =>
      Vediomessage.fromMap(new Map<String, dynamic>.from(source));
}
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-02-07 13:50:15  更:2022-02-07 13:51:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 14:59:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码