zoukankan      html  css  js  c++  java
  • 【Flutter】功能型组件之异步UI更新

    前言

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

  • 相关阅读:
    温故vue对vue计算属性computed的分析
    bootStrap Table 如何使用
    css 的一些知识点的整理
    css 宽高自适应的div 元素 如何居中 垂直居中
    BOM,Dom 回顾
    DOM
    字符串的一些常用方法 string
    js if for 详解 获取元素方式 及一些js 基础知识
    Java入门1
    python字符串
  • 原文地址:https://www.cnblogs.com/parzulpan/p/12321776.html
Copyright © 2011-2022 走看看