Flutter 功能型组件:异步UI更新(FutureBuilder\StreamBuilder)

前言

很多时候会依赖一些异步数据来动态更新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。

原文地址:https://www.cnblogs.com/parzulpan/p/12321776.html

时间: 2024-10-13 18:24:24

Flutter 功能型组件:异步UI更新(FutureBuilder\StreamBuilder)的相关文章

Flutter 功能型组件:跨组件状态共享(Provider)

前言 ??在Flutter开发中,状态管理是一个永恒的话题. ??一般的原则是:如果状态是组件私有的,则应该由组件自己管理:如果状态要跨组件共享,则该状态应该由各个组件共同的父元素来管理. ??对于组件私有的状态管理很好理解,但对于跨组件共享的状态,管理的方式就比较多了,如使用全局事件总线EventBus,它是一个观察者模式的实现,通过它就可以实现跨组件状态同步:状态持有方(发布者)负责更新.发布状态,状态使用方(观察者)监听状态改变事件来执行一些操作. ??但是观察者模式来实现跨组件状态共享有

Flutter 功能型组件:WillPopScope

前言 为了避免用户误触返回按钮而导致APP退出,在很多APP中都拦截了用户点击返回键的按钮,然后进行一些防误触判断,比如当用户在某一个时间段内点击两次时,才会认为用户是要退出(而非误触).Flutter中可以通过WillPopScope来实现返回按钮拦截. 接口描述 const WillPopScope({ Key key, @required this.child, // onWillPop是一个回调函数,当用户点击返回按钮时被调用(包括导航返回按钮及Android物理返回按钮). // 该回

Flutter 可滚动组件:ScrollController

前言 可以用ScrollController来控制可滚动组件的滚动位置. 接口描述 ScrollController({ // 初始滚动位置 double initialScrollOffset = 0.0, // 是否保持滚动位置 this.keepScrollOffset = true, this.debugLabel, }) 代码示例 // ScrollController // 可以用ScrollController来控制可滚动组件的滚动位置. import 'package:flutt

Android开发之UI更新交互机制与实例解析

android开发过程中,经常需要更新UI的状态和文案等.这是就需要对UI进行 更新.在android中更新UI一般有三种方法,handler机制.RunOnUiThread方法以及AsyncTask异步类方法等 本文下面就这三种方法进行了演示和代码实现. a.Handler机制通过使用消息机制来实现 b.RunOnUiThread方法是通过运行UI线程来达到更新UI的目的 c.AsyncTask是异步类,通过异步更新来更新UI 效果图如下:           (1)Java功能实现代码如下:

flutter 输入框组件封装

一.组件分析 ui如下 根据UI分析我们需要提取哪些是动态的,可以通过传递参数得到不同的结果? 1.左侧icon 2.输入的文本 3.是否是密码框 4.输入框的控制器:如何控制输入框的回调函数 二.快速创建自定义组件 vscode中使用快捷键stl快速生成一个无状态组件, class CreateMyInput extends StatelessWidget { @override Widget build(BuildContext context) { return Container( );

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

WPF多线程UI更新--两种方法 前言 在WPF中,在使用多线程在后台进行计算限制的异步操作的时候,如果在后台线程中对UI进行了修改,则会出现一个错误:(调用线程无法访问此对象,因为另一个线程拥有该对象.)这是很常见的一个错误,一不小心就会有这个现象.在WPF中,如果不是用多线程的话,例如单线程应用程序,就是说代码一路过去都在GUI线程运行,可以随意更新任何东西,包括UI对象.但是使用多线程来更新UI就可能会出现以上所说问题,怎么解决?本文章提供两个方法:Dispatcher(大部分人使用),T

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

转自:http://blog.csdn.net/jason0539/article/details/18075293 第一种方法: 遇到一个问题,需要在一个activity中控制另一个acitivity做一些更新,没想到传递handler的方法,通过以下方式解决. 1.在MyAPP中定义属性handler 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package jason.com;     import jas

oc 多线程UI更新

1.在子线程中是不能进行UI 更新的,而可以更新的结果只是一个幻像:因为子线程代码执行完毕了,又自动进入到了主线程,执行了子线程中的UI更新的函数栈,这中间的时间非常的短,就让大家误以为分线程可以更新UI.如果子线程一直在运行,则子线程中的UI更新的函数栈 主线程无法获知,即无法更新 2.只有极少数的UI能,因为开辟线程时会获取当前环境,如点击某个按钮,这个按钮响应的方法是开辟一个子线程,在子线程中对该按钮进行UI 更新是能及时的,如换标题,换背景图,但这没有任何意义

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

我们游戏中会遇到很多UI更新的时候,大部分时候我们会remove该节点,再重新绘制的方法来进行UI更新. 但是这种更新效率并不高,这里我推荐大家一个第三方的库,来通过注册更新的方式来对UI进行更新管理: 它的大名其实很响亮,就是“js-signals”.官方地址:http://www.bootcdn.cn/js-signals/ 官方的定义是:Custom Event/Messaging system for JavaScript.(JavaScript自定义事件的消息传递系统.) 有兴趣的同学