前言

很多时候会依赖一些异步数据来动态更新UI,比如在打开一个页面时我们需要先从互联网上获取数据,在获取数据的过程中我们显示一个加载框,等获取到数据时我们再渲染页面;又比如想展示Stream(比如文件流、互联网数据接收流)的进度。当然,通过StatefulWidget完全可以实现上述这些功能。但由于在实际开发中依赖异步数据更新UI的这种场景非常常见,因此Flutter专门提供了FutureBuilder和StreamBuilder两个组件来快速实现这种功能。

接口描述

FutureBuilder会依赖一个Future,它会根据所依赖的Future的状态来动态构建自身。描述如下:

FutureBuilder({
// FutureBuilder依赖的Future,通常是一个异步耗时任务
this.future,
// 初始数据,用户设置默认数据
this.initialData,
// Widget构建器,该构建器会在Future执行的不同阶段被多次调用
// 构建器签名为:Function(BuildContext context, AsyncSnapshot snapshot)
// snapshot会包含当前异步任务的状态信息及结果信息,比如可以通过snapshot.connectionState获取异步任务的状态信息,通过snapshot.hasError判断任务时候有错误等
@required this.builder,
}) StreamBuilder({
Key key,
this.initialData,
Stream<T> stream,
@required this.builder,
})

代码示例

// 异步UI更新(FutureBuilder\StreamBuilder)

import 'dart:math';

import 'package:flutter/material.dart';

// 实现一个路由,当该路由打开时我们从网上获取数据,获取数据时弹一个加载框;获取结束时,如果成功则显示获取到的数据,如果失败则显示错误。
// 不真正去网络请求数据,而是模拟一下这个过程,隔3秒后返回一个字符串
Future<String> mockNetworkData() async{
return Future.delayed(Duration(seconds: 2), () => "我是从互联网上获取的数据!");
} class FutureBuilderTest extends StatelessWidget{
@override
Widget build(BuildContext context){
return Center(
child: FutureBuilder<String>(
future: mockNetworkData(),
builder: (BuildContext context, AsyncSnapshot snapshot){
// 请求已结束
if(snapshot.connectionState == ConnectionState.done){
if(snapshot.hasError){
// 请求失败,显示错误
return Text("Error: ${snapshot.error}");
}else{
// 请求成功,显示数据
return Text("Contents: ${snapshot.data}");
}
}else{
// 请求未结束,显示loading
return CircularProgressIndicator();
}
},
),
);
}
} // 创建一个计时器的示例:每隔1秒,计数加1。这里,使用Stream来实现每隔一秒生成一个数字。
Stream<int> counter(){
return Stream.periodic(Duration(seconds: 1), (i){
return i;
});
} class StreamBuilderTest extends StatelessWidget{
@override
Widget build(BuildContext context){
return StreamBuilder<int>(
stream: counter(),
builder: (BuildContext context, AsyncSnapshot<int> snapshot){
if(snapshot.hasError)
return Text("Error: ${snapshot.error}");
switch(snapshot.connectionState){
case ConnectionState.none:
return Text("没有Stream");
case ConnectionState.waiting:
return Text("等待数据...");
case ConnectionState.active:
// TODO: Handle this case.
return Text("active:${snapshot.data}");
case ConnectionState.done:
// TODO: Handle this case.
return Text("Stream已关闭");
}
return null;
},
);
}
}

总结

Dart中Stream 也是用于接收异步事件数据,和Future 不同的是,它可以接收多个异步操作的结果,它常用于会多次读取数据的异步任务场景,如网络内容下载、文件读写等。StreamBuilder正是用于配合Stream来展示流上事件(数据)变化的UI组件。在实战中,凡是UI会依赖多个异步数据而发生变化的场景都可以使用StreamBuilder。

【Flutter】功能型组件之异步UI更新的更多相关文章

  1. 执行异步UI更新

    异步更新UI的几种方法①.使用Control.Invoke方式来更新数据                     foreach (DataGridViewRow dgvr in this.dgv_s ...

  2. C#.NET使用Task,await,async,异步执行控件耗时事件(event),不阻塞UI线程和不跨线程执行UI更新,以及其他方式比较

    使用Task,await,async,异步执行事件(event),不阻塞UI线程和不跨线程执行UI更新 使用Task,await,async 的异步模式 去执行事件(event) 解决不阻塞UI线程和 ...

  3. Flutter走过的坑(持续更新)

    1 Target of URI doesn't exist 'package:flutter/material.dart' 官方下载的flutter中有一个example文件夹,里面有很多flutte ...

  4. Flutter InkWell - Flutter每周一组件

    Flutter Inkwell使用详解 该文章属于[Flutter每周一组件]系列,其它组件可以查看该系列下的文章,该系列会不间断更新:所有组件的demo已经上传值Github: https://gi ...

  5. Flutter ListTile - Flutter每周一组件

    该文章属于[Flutter每周一组件]系列,其它组件可以查看该系列下的文章,该系列会不间断更新:所有组件的demo已经上传值Github: https://github.com/xj124456/fl ...

  6. 免费素材:包含 250+ 组件的 DO UI Kit

    DO UI kit 现在可以免费用于 Photoshop 和 Sketch 了.它有超过130个屏幕,10个完整的主题以及250+的组件混合以创造惊人的应用.他们都是再混合和视网膜.最重要的是他们看起 ...

  7. android开发之在activity中控制另一个activity的UI更新

    转自:http://blog.csdn.net/jason0539/article/details/18075293 第一种方法: 遇到一个问题,需要在一个activity中控制另一个acitivit ...

  8. 【Cocos2d-Js基础教学(7)界面UI更新方法(会用到第三方类库)】

    我们游戏中会遇到很多UI更新的时候,大部分时候我们会remove该节点,再重新绘制的方法来进行UI更新. 但是这种更新效率并不高,这里我推荐大家一个第三方的库,来通过注册更新的方式来对UI进行更新管理 ...

  9. WPF多线程UI更新——两种方法

    WPF多线程UI更新——两种方法 前言 在WPF中,在使用多线程在后台进行计算限制的异步操作的时候,如果在后台线程中对UI进行了修改,则会出现一个错误:(调用线程无法访问此对象,因为另一个线程拥有该对 ...

随机推荐

  1. 五、git学习之——分支管理策略、Bug分支、feature分支、多人协作

    一.分支管理策略 通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息. 如果要强制禁用Fast forward模式,Git就会在merge时生 ...

  2. jwt与springcloud联用

    图片来源与博客:https://www.jianshu.com/p/99a458c62aa4 分布式权限管理参考:https://blog.csdn.net/qq_36236890/article/d ...

  3. Canal监听mysql

    安装mysql5.7,并开启binlog 安装mysql 开启binlog find / -name my.cnf 找到这个文件 添加几行 [mysqld] log-bin=mysql-bin # 开 ...

  4. 记录一次mac访问Windows共享目录失败

    一,起因 起因,有人联系我说他们的mac电脑连接不上Windows的共享目录,Windows的电脑连接正常,没有报错,连接框抖两下就没了 二,排查问题 1,我自己想mstsc登陆服务器看看,结果服务器 ...

  5. Unity 保存游戏,读取游戏,退出游戏

    1 using System.Collections; 2 using System.Collections.Generic; 3 using UnityEngine; 4 using System. ...

  6. scala安装遇到的问题:[ERROR] Failed to construct terminal; falling back to unsupported java.lang.NumberFormatException: For input string: "0x100"

    安装scala时遇到的问题 lion@king:/opt$ scala Welcome to Scala 2.11.12 (Java HotSpot(TM) 64-Bit Server VM, Jav ...

  7. springMVC基础讲解

    一.初识三层架构: 在讲解springMVC之前,先来了解一下什么是三层架构.我们的开发架构一般都是基于两种形式,一种是C/S架构(客户端/服务器),另一种是B/S架构(浏览器服务器).在javaEE ...

  8. Spark-1-调优基本原则

    1基本概念和原则 每一台host上面可以并行N个worker,每一个worker下面可以并行M个executor,task们会被分配到executor上面去执行.Stage指的是一组并行运行的task ...

  9. 多任务-python实现-使用队列完成进程间的通信(2.1.8)

    @ 目录 1.为什么要使用队列 2.python代码实现 1.为什么要使用队列 进程之间是互相独立的,而线程能够共享全局变量 所以如果进程间想要交换数据的话 只有通过进程间的通信,比如socket.太 ...

  10. aaencode:用颜文字来加密吧

    今天逛大佬博客发现了一个有意思的东西 ゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚ ...