Flutter 异步Future与FutureBuilder实用技巧
什么是Future?
Future表示在接下来的某个时间的值或错误,借助Future我们可以在Flutter实现异步操作。它类似于ES6中的Promise,提供then和catchError的链式调用。
Future是dart:async包中的一个类,使用它时需要导入dart:async包,Future有两种状态:
- pending - 执行中;
- completed - 执行结束,分两种情况要么成功要么失败;
Future的常见用法?
- 使用
future.then获取future的值与捕获future的异常 - 结合
async,await future.whenCompletefuture.timeout
使用future.then获取future的值与捕获future的异常
import 'dart:async';
Future<String> testFuture() {
// throw new Error();
return Future.value('success');
// return Future.error('error');
} main() {
testFuture().then((s) {
print(s);
}, onError: (e) {
print('onError:');
print(e);
}).catchError((e) {
print('catchError:');
print(e);
});
}
Future的then的原型:
Future<R> then<R>(FutureOr<R> onValue(T value), {Function onError});
第一个参数会成功的结果回调,第二个参数onError可选表示执行出现异常。
结合async await
Future是异步的,如果我们要将异步转同步,那么可以借助 async await来完成。
import 'dart:async';
test() async {
int result = await Future.delayed(Duration(milliseconds: ), () {
return Future.value();
});
print('t3:' + DateTime.now().toString());
print(result);
}
main() {
print('t1:' + DateTime.now().toString());
test();
print('t2:' + DateTime.now().toString());
}
future.whenComplete
有时候我们需要在Future结束的时候做些事情,我们知道then().catchError()的模式类似于try-catch,try-catch有个finally代码块,而future.whenComplete就是Future的finally。
import 'dart:async';
import 'dart:math'; void main() {
var random = Random();
Future.delayed(Duration(seconds: ), () {
if (random.nextBool()) {
return ;
} else {
throw 'boom!';
}
}).then(print).catchError(print).whenComplete(() {
print('done!');
});
}
future.timeout
完成一个异步操作可能需要很长的时间,比如:网络请求,但有时我们需要为异步操作设置一个超时时间,那么,如何为Future设置超时时间呢?
import 'dart:async';
void main() {
new Future.delayed(new Duration(seconds: ), () {
return ;
}).timeout(new Duration(seconds: )).then(print).catchError(print);
}
运行上述代码会看到:TimeoutException after 0:00:02.000000: Future not completed
什么是FutureBuilder?
FutureBuilder是一个将异步操作和异步UI更新结合在一起的类,通过它我们可以将网络请求,数据库读取等的结果更新的页面上。
FutureBuilder的构造方法
FutureBuilder({Key key, Future<T> future, T initialData, @required AsyncWidgetBuilder<T> builder })
future: Future对象表示此构建器当前连接的异步计算;initialData: 表示一个非空的Future完成前的初始化数据;builder: AsyncWidgetBuilder类型的回到函数,是一个基于异步交互构建widget的函数;
这个builder函数接受两个参数BuildContext context与 AsyncSnapshot<T> snapshot,它返回一个widget。AsyncSnapshot包含异步计算的信息,它具有以下属性:
connectionState - 枚举ConnectionState的值,表示与异步计算的连接状态,ConnectionState有四个值:none,waiting,active和done;
data - 异步计算接收的最新数据;
error - 异步计算接收的最新错误对象;
AsyncSnapshot还具有hasData和hasError属性,以分别检查它是否包含非空数据值或错误值。
现在我们可以看到使用FutureBuilder的基本模式。在创建新的FutureBuilder对象时,我们将Future对象作为要处理的异步计算传递。 在构建器函数中,我们检查connectionState的值,并使用AsyncSnapshot中的数据或错误返回不同的窗口小部件。
FutureBuilder的使用?
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http; void main() => runApp(new MyApp()); class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() => _MyAppState();
} class _MyAppState extends State<MyApp> {
String showResult = '';
Future<CommonModel> fetchPost() async {
final response = await http .get('http://www.devio.org/io/flutter_app/json/test_common_model.json');
Utf8Decoder utf8decoder = Utf8Decoder(); //fix 中文乱码
var result = json.decode(utf8decoder.convert(response.bodyBytes));
return CommonModel.fromJson(result);
} @override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Future与FutureBuilder实用技巧'),
), body: FutureBuilder<CommonModel>(
future: fetchPost(),
builder:
(BuildContext context, AsyncSnapshot<CommonModel> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return new Text('Input a URL to start');
case ConnectionState.waiting:
return new Center(child: new CircularProgressIndicator());
case ConnectionState.active:
return new Text('');
case ConnectionState.done:
if (snapshot.hasError) {
return new Text(
'${snapshot.error}',
style: TextStyle(color: Colors.red),
);
} else {
return new Column(children: <Widget>[
Text('icon:${snapshot.data.icon}'),
Text('statusBarColor:${snapshot.data.statusBarColor}'),
Text('title:${snapshot.data.title}'),
Text('url:${snapshot.data.url}')
]);
}
}
}),
),
);
}
} class CommonModel {
final String icon;
final String title;
final String url;
final String statusBarColor;
final bool hideAppBar;
CommonModel(
{this.icon, this.title, this.url, this.statusBarColor, this.hideAppBar});
factory CommonModel.fromJson(Map<String, dynamic> json) {
return CommonModel(
icon: json['icon'],
title: json['title'],
url: json['url'],
statusBarColor: json['statusBarColor'],
hideAppBar: json['hideAppBar'],
);
}
}
Flutter 异步Future与FutureBuilder实用技巧的更多相关文章
- Flutter异步Future
一.认识Future 1.创建Future void testFuture(){ Future future = new Future(() => null); future.then((_){ ...
- 总结vue知识体系之实用技巧
vue 作为目前前端三大框架之一,对于前端开发者可以说是必备技能.那么怎么系统地学习和掌握 vue 呢?为此,我做了简单的知识体系体系总结,不足之处请各位大佬多多包涵和指正,如果喜欢的可以点个小赞!本 ...
- Notepad++ 实用技巧
Notepad++是一款开源的文本编辑器,功能强大.很适合用于编辑.注释代码.它支持绝大部分主流的编程语言. 本文主要列举了本人在实际使用中遇到的一些技巧. 快捷键 自定义快捷键 首先,需要知道的是: ...
- javascript实用技巧、javascript高级技巧
字号+作者:H5之家 来源:H5之家 2016-10-31 11:00 我要评论( ) 三零网提供网络编程. JavaScript 的技术文章javascript实用技巧.javascript高级技巧 ...
- iOS开发实用技巧—Objective-C中的各种遍历(迭代)方式
iOS开发实用技巧—Objective-C中的各种遍历(迭代)方式 说明: 1)该文简短介绍在iOS开发中遍历字典.数组和集合的几种常见方式. 2)该文对应的代码可以在下面的地址获得:https:// ...
- iOS开发实用技巧—在手机浏览器头部弹出app应用下载提示
iOS开发实用技巧—在手机浏览器头部弹出app应用下载提示 本文介绍其简单使用: 第一步:在本地建立一个访问的服务端. 打开本地终端,在本地新建一个文件夹,在该文件夹中存放测试的html页面. ...
- iOS开发实用技巧—项目新特性页面的处理
iOS开发实用技巧篇—项目新特性页面的处理 说明:本文主要说明在项目开发中会涉及到的最最简单的新特性界面(实用UIScrollView展示多张图片的轮播)的处理. 代码示例: 新建一个专门的处理新特性 ...
- IOS 网络浅析-(十三 SDWebImage 实用技巧)
IOS 网络浅析-(十三 SDWebImage 实用技巧) 首先让我描述一下为了什么而产生的实用技巧.(在TableView.CollectionView中)当用户所处环境WiFi网速不够快(不能立即 ...
- NSString的八条实用技巧
NSString的八条实用技巧 有一篇文章写了:iOS开发之NSString的几条实用技巧 , 今天这篇,我们讲讲NSString的八条实用技巧.大家可以收藏起来,方便开发随时可以复制粘贴. 0.首字 ...
随机推荐
- Cairo初探
https://blog.csdn.net/flexwang_/article/details/38000401 二维解析pdf
- BOOTP引导程序协议
我们介绍了一个无盘系统,它在不知道自身 I P地址的情况下,在进行系统引导时能够通过R A R P来获取它的I P地址.然而使用R A R P有两个问题:(1)I P地址是返回的唯一结果:(2)既然R ...
- nginx 普通用户使用80端口启动nginx
方法一: 依次执行如下命令 cd /usr/local/nginx/sbin/ chown root nginx chmod u+s nginx 优点是,方便简单,缺点是,既然sudo权限都不给了.这 ...
- python 杂记 网络
参考资料:https://www.cnblogs.com/gareth-yu/p/9097943.htmlimport selectors import socket sel = selectors. ...
- 3、python--第三天练习题
#1.简述普通参数.指定参数.默认参数.动态参数的区别 #1.普通参数就是传入的函数,没有默认值 def f(a): a = a + 1 return a print(f(3)) #2.指定参数 de ...
- P4317 花神的数论题 动态规划?数位DP
思路:数位$DP$ 提交:5次(其实之前A过,但是调了调当初的程序.本次是2次AC的) 题解: 我们分别求出$sum(x)=i$,对于一个$i$,有几个$x$,然后我们就可以快速幂解决. 至于求个数用 ...
- jQuery.proxy(function,context)
jQuery.proxy(function,context) 概述 jQuery 1.4 新增.返回一个新函数,并且这个函数始终保持了特定的作用域.大理石平台检定规程 当有事件处理函数要附加到元素上, ...
- vue中setInterval的清除
两种清除setInterval的方式: 方案一: data() { return { timer: null // 定时器名称 } }, mouted() { this.timer = (() =&g ...
- Cogs 1500. 误差曲线(三分)
误差曲线 ★★ 输入文件:errorcurves.in 输出文件:errorcurves.out 评测插件 时间限制:1 s 内存限制:256 MB [题目描述] Josephina是一名聪明的妹子, ...
- php win/linux/mac 安装redis扩展或者扩展报错 zend_smart_str.h file not found
1 windows 安装reids 扩展 根据phpinfo 查看php信息.在pecl.php.net 下载对应的redis扩展版本,放如扩展目录,在php.ini 配置扩展信息,重启服务 2 li ...