饿补一下Flutter中Http请求的异步操作。

Dart是一个单线程语言,可以理解成物理线路中的串联,当其遇到有延迟的运算(比如IO操作、延时执行)时,线程中按顺序执行的运算就会阻塞,用户就会感觉到卡顿,于是通常用异步处理来解决这个问题。

Dart异步编程有两种方式:Future和Stream

Future相当于40米大砍刀,Stream相当于一捆40米大砍刀。dart提供了关键字async(异步)和await(延迟执行),相当于普通的便捷的小匕首,而小匕首是我们平时经常用到的。

当遇到有需要延迟的运算(async)时,将其放入到延迟运算的队列(await)中去,把不需要延迟运算的部分先执行掉,最后再来处理延迟运算的部分。

1、async和await

async await 这两个关键字是dart语言的特性,能让你写出看起来像是“同步”的“异步”代码,先看一个方法案例:

  /*HTTP的get请求返回值为Future<String>类型,即其返回值未来是一个String类型的值*/
  /*async关键字声明该函数内部有代码需要延迟执行*/
  getData() async {    
    /*await关键字声明运算为延迟执行,然后return运算结果*/
    return await http.get(Uri.encodeFull(url), headers: {"Accept": "application/json"}); 
  }

然后我们尝试调用这个方法,并获取返回值。

String data = getDate();

然后控制台报错了….

为什么呢?因为data是String类型,而函数getData()是一个异步操作函数,其返回值是一个await延迟执行的结果。在Dart中,有await标记的运算,其结果值都是一个Future对象,Future不是String类型,所以就报错了。

总结一下:

在请求方法中直接 return await .. .的时候,实际上返回的是一个延迟计算的Future对象。

还有两点需要注意:

  • await关键字必须在async函数内部使用
  • 调用async函数必须使用await关键字

后面两点怎么讲?

  1. 要想 return await … ,那么方法首先是 async 的,如上方方法。
  2. 使用 async 标注的方法,必须要用 await 接收返回值,比如上方方法在接收返回值时,需要加入 await ,var data = await getData();

2、什么是Future

Future表示一件“将来”会发生的事情,将来可以从Future中取到一个值。当一个方法返回一个Future的事情,发生两件事情:

  • 这个方法将某件事情排队,返回一个未完成的Future
  • 当这件事情完毕之后,Future的状态会变成已完成,这个时候就可以取到这件事情的返回值了。

要取到这个“返回值”,有两种方式:

  • 使用async配合await
  • 使用Future提供的api

我们看这两种实现方式的案例:

2.1、使用async配合await

先看个案例,等待3秒后返回‘我是用户’:

/*模拟异步加载用户信息*/
Future _getUserInfo() async{
  await new Future.delayed(new Duration(milliseconds: 3000));
  return "我是用户";
} /*加载用户信息,顺便打印时间看看顺序*/
Future _loadUserInfo() async{
  print("_loadUserInfo:${new DateTime.now()}");
  print(await _getUserInfo());
  print("_loadUserInfo:${new DateTime.now()}");
}

我们在initState中调用该方法:

@override
void initState(){
    print("initState:${new DateTime.now()}");
    _loadUserInfo();
    print("initState:${new DateTime.now()}");     super.initState();
}

打印结果如下:

I/flutter ( 1802): initState:2019-06-20 09:46:40.097339
I/flutter ( 1802): _loadUserInfo:2019-06-20 09:46:40.103542
I/flutter ( 1802): Instance of 'Future<dynamic>'
I/flutter ( 1802): initState:2019-06-20 09:46:40.108510
I/flutter ( 1802): 我是用户
I/flutter ( 1802): _loadUserInfo:2019-06-20 09:46:43.117136

what?

很明显,打印结果并没有按照串联的方式依次打印。

flutter中会改造带asyc关键字的方法,让这个方法脱离主流程,变成“后面一点”执行(通过scheduleMicrotask),所以可以让我们的程序“看起来”是顺序执行的。

2.2、Future api

我们修改一下 loadUserInfo() 方法:

/*加载用户信息,顺便打印时间看看顺序*/
  Future _loadUserInfo() async{
    print("_loadUserInfo:${new DateTime.now()}");
    _getUserInfo().then((info){
      print(info);
    });
    print("_loadUserInfo:${new DateTime.now()}");
  }

再次运行输出一下:

I/flutter ( 1802): initState:2019-06-20 09:50:32.488765
I/flutter ( 1802): _loadUserInfo:2019-06-20 09:50:32.494751
I/flutter ( 1802): _loadUserInfo:2019-06-20 09:50:32.499725
I/flutter ( 1802): Instance of 'Future<dynamic>'
I/flutter ( 1802): initState:2019-06-20 09:50:32.499970
I/flutter ( 1802): 我是用户

两次输出是有不同的,主要不同在于第二个 loadUserInfo 的日志打印,与‘我是用户’的输出顺序,为什么有差异?

await会阻塞流程,等待紧跟着的的Future执行完毕之后,再执行下一条语句,而如果用了Future.then这个api,那么就不会等待,直接执行下面的语句,等Future执行完了,再调用then这个方法。

3、总结

在请求方法中直接 return await .. .的时候,实际上返回的是一个延迟计算的Future对象。

有两点需要注意:

  • await关键字必须在async函数内部使用
  • 调用async函数必须使用await关键字

Flutter 中有两种实现异步编程的方式:Future api、 async await

日常开发中常用的是 async await Future 搭配。

最新文章

  1. 什么是ORM?
  2. 网络HTTP协议
  3. ASP.NET MVC3 Razor 初心者容易遇到的問題(转)
  4. 常见HTTP状态码
  5. (翻译)如何对python dict 类型按键(keys)或值(values)排序
  6. HttpURLConnection网络请求
  7. CentOS 6.5系统上安装SVN服务器端的方法及步骤
  8. poj 2425 A Chess Game 博弈论
  9. WebView介绍
  10. 安装 Homebrew
  11. 关于Installation error: INSTALL_FAILED_MISSING_SHARED_LIBRARY
  12. android屏幕适配之度量单位、屏幕分类、图标尺寸归类分析
  13. C# using
  14. C++高效安全的运行时动态类型转换
  15. 关于ArcMap中打开ArcToolbox导致闪退的解决办法
  16. Python3.6及以上pip安装pymssql错误的解决办法[Windows&amp;Linux freetds安装]
  17. 5、Storm集成Kafka
  18. 微信小程序 - 相对定位和绝对定位 - 相对路径和绝对路径
  19. JSP页面分页显示数据
  20. 简单的Verilog测试模板结构

热门文章

  1. Java学习:异常的概念
  2. 给定一个长度为N的数组,找出出现次数大于n/2,n/3的数,要求时间复杂度O(n),空间复杂度O(1)
  3. DELL OptiPlex 7050M黑苹果纪录
  4. Smobiler客户端会话
  5. Puppet自动化管理配置
  6. 2019-08-01 JQuery事件
  7. Vue.js前端MVVM框架实战篇
  8. restFull api接口
  9. Python 的稀疏矩阵
  10. 深入理解 ValueTask