一般程序员都会了解,类似于 IO、网络请求等都应该是异步的。

在Dart中,我们使用 Future 来管理,这样就不用担心线程或者死锁的问题。

那么当 Flutter 涉及到 Future 的时候,widget 该如何去构建呢?

在网络请求 开始前、请求中、请求完成或失败,我们应该如何去管理我们的UI?

为此,Flutter 推出 FutureBuilder。

什么是FutureBuilder

先看文档:

Widget that builds itself based on the latest snapshot of interaction with a Future.

翻译过来说就是 FutureBuilder 是基于 Future 快照来构建自身的一个组件。

快照是啥玩意?个人理解就是这个 Future 目前的信息。

这个信息里面包括:目前的状态、所携带的数据等等

如何使用

先看看 FutureBuilder 是个啥, 点开源码:

class FutureBuilder<T> extends StatefulWidget {const FutureBuilder({Key key,this.future,this.initialData,@required this.builder,}) : assert(builder != null),super(key: key);
}final AsyncWidgetBuilder<T> builder;
复制代码

看出来是个有状态的小部件,找到 State 的 build 方法:

Widget build(BuildContext context) => widget.builder(context, _snapshot);

build 方法直接返回了一个 widget 的 builder。

那我们继续,打开官网看官方Demo怎么写的:

FutureBuilder<String>(future: _calculation, // a previously-obtained Future<String> or nullbuilder: (BuildContext context, AsyncSnapshot<String> snapshot) {switch (snapshot.connectionState) {case ConnectionState.none:return Text('Press button to start.');case ConnectionState.active:case ConnectionState.waiting:return Text('Awaiting result...');case ConnectionState.done:if (snapshot.hasError)return Text('Error: ${snapshot.error}');return Text('Result: ${snapshot.data}');}return null; // unreachable},
)
复制代码

可以看到 FutureBuilder 定义了一个泛型,这个泛型是用来获取快照中数据时用的。

FlutureBuilder 有两个参数:

future:这个参数需要一个 Future 对象,类似于 网络请求、IO

builder:这个参数需返回一个 widget,我们可以看到 demo 中根据现在快照不同的连接状态返回不同的 widget。

我们再来看一下 snapshot.connectionState都有哪些值:

ConnectionState 当前没有连接到任何的异步任务
ConnectionState.none 当前没有连接到任何的异步任务
ConnectionState.waiting 连接到异步任务并等待进行交互
ConnectionState.active 连接到异步任务并开始交互
ConnectionState.done 异步任务中止

现在了解了之后我们就可以有想法了。

我们在打开一个页面的时候肯定会有网络请求,这个时候要显示 loading 之类的,我们就可以利用当前快照的状态来返回不同的 widget,比如这样:

首先看build代码:

@override
Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('FutureBuilderPage'),),body: FutureBuilder(builder: (context, snapshot) {switch (snapshot.connectionState) {case ConnectionState.none:case ConnectionState.active:case ConnectionState.waiting:print('waiting');return Center(child: CupertinoActivityIndicator());case ConnectionState.done:print('done');if (snapshot.hasError) {return Center(child: Text('网络请求出错'),);}return generateListView();}return null;},future: _future,),);
}
复制代码

Scaffold 的 body 直接返回一个 FutureBuilder,根据不同状态来返回了不同的 widget。

**这里需要注意的一点是:**我们知道 StatefulWidget会长时间维护一个 State,当有变动的时候会调用 didUpdateWidget方法,就要重新build了。所以FutureBuilder的官方文档上有这么一段文字:

The future must have been obtained earlier, e.g. during State.initState, State.didUpdateConfig, or State.didChangeDependencies. It must not be created during the State.build or StatelessWidget.buildmethod call when constructing the FutureBuilder. If the future is created at the same time as the FutureBuilder, then every time the FutureBuilder's parent is rebuilt, the asynchronous task will be restarted.

A general guideline is to assume that every build method could get called every frame, and to treat omitted calls as an optimization.

大致意思就是说 future 这个参数建议在 initState() 里初始化,不要在 build 方法里初始化,这样的话会一直 rebuild。

为什么呢,我们查看 didUpdateWidget 源码:

@override
void didUpdateWidget(FutureBuilder<T> oldWidget) {super.didUpdateWidget(oldWidget);if (oldWidget.future != widget.future) {if (_activeCallbackIdentity != null) {_unsubscribe();_snapshot = _snapshot.inState(ConnectionState.none);}_subscribe();}
}
复制代码

可以看出来这里是判断了 future 这个字段,所以我们一定不要在 build 方法里初始化 future 参数!

所以,我们在 initState()方法里初始化:

Future _future;
Dio _dio;
int date = 20190523;
List<Stories> _newsData = [];@override
void initState() {super.initState();_dio = Dio();_future = getNewsList();
}// 获取知乎每天的新闻,数据获取成功后 setState来刷新数据
Future getNewsList() async {var response =await _dio.get('https://news-at.zhihu.com/api/4/news/before/$date');setState(() {_newsData.addAll(ZhiHuNews.fromJson(response.data)._stories);});
}
复制代码

generateListView 方法就不放了,就是基本的 ListView.builder()。

这样我们就完成了上图的效果,在网络请求的时候加载小菊花,请求成功加载出 ListView.

小结

可以看得出来 FutureBuilder 确实是非常方便,而且我们可以自己封装几个控件,后面用的时候就会更加完美。

如想获取源码请移步本人Github:github.com/wanglu1209/…

转载于:https://juejin.im/post/5ce73d33f265da1bc8540261

Flutter FutureBuilder 异步UI神器相关推荐

  1. 【Flutter】FutureBuilder 异步编程 ( FutureBuilder 构造方法 | AsyncSnapshot 异步计算 )

    文章目录 一.FutureBuilder 简介 二.FutureBuilder 构造方法 三.AsyncSnapshot 异步计算 四.相关资源 一.FutureBuilder 简介 FutureBu ...

  2. zk ui_高级ZK:异步UI更新和后台处理–第2部分

    zk ui 介绍 在第1部分中,我展示了如何在ZK应用程序中使用服务器推送和线程来执行后台任务. 但是,这个简单的示例具有一个重大缺陷,这使其对于实际应用程序而言是一种不好的方法:它为每个后台任务启动 ...

  3. zk ui_高级ZK:异步UI更新和后台处理–第1部分

    zk ui 异步UI更新非常有用,因为它们通常可以提高响应性,可用性和用户界面的总体感觉. 我将在这里重点介绍ZK框架,但是通常,相同的原理也适用于桌面UI(Swing,SWT). 长时间运行的处理 ...

  4. 高级ZK:异步UI更新和后台处理–第2部分

    介绍 在第1部分中,我展示了如何在ZK应用程序中使用服务器推送和线程来执行后台任务. 但是,这个简单的示例具有一个重大缺陷,这使其对于实际应用程序而言是一种不好的方法:它为每个后台任务启动了一个新线程 ...

  5. 高级ZK:异步UI更新和后台处理–第1部分

    异步UI更新非常有用,因为它们通常可以提高响应性,可用性和用户界面的总体感觉. 我将在这里重点介绍ZK框架,但是通常,相同的原理也适用于桌面UI(Swing,SWT). 长时间运行的处理 有时,您可能 ...

  6. 分布式异步任务神器-Celery

    最近研究了下异步任务神器-Celery,发现非常好用,可以说是高可用,假如你发出一个任务执行命令给 Celery,只要 Celery 的执行单元 (worker) 在运行,那么它一定会执行:如果执行单 ...

  7. flutter仿微信ui

    flutter仿微信ui 目录 flutter仿微信ui 项目结构 项目搭建 运行效果 代码 参考书籍 项目结构 项目搭建 pubspec.yaml的pub get 项目中message模块的mess ...

  8. 【Flutter】Future 与 FutureBuilder 异步编程代码示例 ( FutureBuilder 构造函数设置 | 处理 Flutter 中文乱码 | 完整代码示例 )

    文章目录 一.FutureBuilder 简介 二.处理 Flutter 中的中文乱码 三.完整代码示例 四.相关资源 一.FutureBuilder 简介 FutureBuilder 本质是组件 : ...

  9. Flutter性能优化—UI

    耗时三个月总结全网大部分Flutter性能分析的方法论,并且结合实战验证效果和自己开发经验,保姆式的一步步带你了解优化中的细节和注意点,希望能给你带来一些收获 原理 Flutter的架构 Framew ...

最新文章

  1. wireshark 总体结构
  2. android 之Activity的五种传值方式 (在从当前Activity跳转到目标Activity时的传值方式)
  3. 《算法竞赛入门经典》 例题 4-1 古老的密码(Ancient Cipher) UVa 1339
  4. Android成长日记-使用GridView显示多行数据
  5. redis和mysql数据不一致_高并发下为什么 redis 和数据库不一致?怎么解决?
  6. python ddt
  7. 部署 shell Linux
  8. php编写数据库配置文件,通用php与mysql数据库配置文件
  9. DateUtils工具类
  10. KeilC51基础 改变代码的字体大小
  11. 18个Windows应该有却没有具有的服从(2)
  12. 华为防火墙做单臂路由_华为单臂路由配置详解
  13. 【LeetCode】18. 4Sum 四数之和
  14. java 调试sql server_sql server 如何调试存储过程
  15. c语言编程齿轮模数选择,如何画齿轮,一看就懂
  16. 互联网公司分布式系统架构演进之路
  17. 【快速上手教程1】疯壳·开源编队无人机-开机测试
  18. 用计算机寻找规律,用计算器找规律练习题
  19. Windows 9操作系统已经开始测试!
  20. 消费商时代来临,日常消费成为投资

热门文章

  1. 上拉电阻 以及 阻抗匹配
  2. 全媒体运营师胡耀文教你:从0到专业玩转活动运营
  3. 发票扫描识别技术的应用
  4. java对接银联商务公众号+服务窗支付(1)
  5. 首届中国优秀游戏制作人评选大赛颁奖典礼在京举行
  6. anaconda安装完找不到.jupyter目录
  7. B轮融资成功,致谢今目标用户
  8. 易语言大漠多线程模板脚本主线程
  9. 递归思想求解稀疏多项式的值
  10. 新华三智慧酒店解决方案