5、 Flutter Widgets 之 FutureBuilder

·  阅读 11459
 5、 Flutter Widgets 之 FutureBuilder

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情

展示异步任务状态

当有一个Future(异步)任务需要展示给用户时,可以使用FutureBuilder控件来完成,比如向服务器发送数据成功时显示成功提示:

import 'package:flutter/material.dart';
 
class WyFutureBuilder extends StatefulWidget {
  @override
  _WyFutureBuilderState createState() => _WyFutureBuilderState();
}
 
class _WyFutureBuilderState extends State<WyFutureBuilder> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('FutureBuilder'),
      ),
      body: _creactFutureBuilder(),
    );
  }
 
  var _future = Future.delayed(Duration(seconds: 5), () {
    return '老王,一个有态度的程序员';
  });
 
  Widget _creactFutureBuilder() {
    return FutureBuilder(
        future: _future,
        builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
          var widget;
          if (snapshot.connectionState == ConnectionState.done) {
            if (snapshot.hasError) {
              widget = Icon(
                Icons.error,
                color: Colors.red,
                size: 48,
              );
            } else {
              widget = Icon(
                Icons.check_circle,
                color: Colors.green,
                size: 36,
              );
            }
          } else {
            widget = Padding(
              padding: EdgeInsets.all(20),
              child: CircularProgressIndicator(),
            );
          }
 
          return Center(
            child: Container(
              height: 100,
              width: 100,
              decoration: BoxDecoration(
                  border: Border.all(color: Colors.grey),
                  borderRadius: BorderRadius.all(Radius.circular(10))),
              child: widget,
            ),
          );
        });
  }
}
复制代码

图片.png

在Future任务中出现异常如何处理,下面模拟出现异常,修改_future:

var _future = Future.delayed(Duration(seconds: 3), () {
 
    return Future.error('');
  });
复制代码

builder是FutureBuilder的构建函数,在这里可以判断状态及数据显示不同的UI, ConnectionState的状态包含四种:none、waiting、active、done,但我们只需要关注done状态,此状态表示Future执行完成,snapshot参数的类型是AsyncSnapshot。

ListView加载网络数据

FutureBuilder还有一个比较常用的场景:网络加载数据并列表展示,这是一个非常常见的功能,在网络请求过程中显示loading,请求失败时显示失败UI,成功时显示成功UI。

模拟成功网络请求,通常会返回json字符串:

    var _future = Future.delayed(Duration(seconds: 3), () {
    return 'json 字符串';
  });
复制代码
     //构建FutureBuilder控件:
  Widget _createListView(){
    return FutureBuilder(
        future: _future,
        builder: (context, snapshot) {
          var widget;
          if (snapshot.connectionState == ConnectionState.done) {
            if (snapshot.hasError) {
              widget = _loadingErrorWidget();
            } else {
              widget = _dataWidget(snapshot.data);
            }
          } else {
            widget = _loadingWidget();
          }
          return widget;
        });
  }
  //构建loading控件:
  _loadingWidget(){
    return Center(
      child: Padding(
        padding: EdgeInsets.all(20),
        child: CircularProgressIndicator(),
      ),
    );
  }
  //数据加载成功,构建数据展示控件:
  _dataWidget(data){
      return ListView.separated(itemBuilder: (context,index){
        return Container(
          height: 60,
          alignment: Alignment.center,
          child: Text('$index',style: TextStyle(fontSize: 20),),
        );
      },
          separatorBuilder: (context,index){
            return Divider();
          },
          itemCount: 10);
  }
//构建网络加载失败控件:
  _loadingErrorWidget() {
 
    return Center(
      child: Text('数据加载失败,请重试。'),
    );
  }
复制代码

图片.png

模拟网络加载失败:

var _future = Future.delayed(Duration(seconds: 3), () {

   return Future.error('');
 });
复制代码

通过上面的示例说明FutureBuilder控件极大的简化了异步任务相关显示的控件,不再需要开发者自己维护各种状态以及更新时调用State.setState

防止FutureBuilder重绘

FutureBuilder是一个StatefulWidget控件,如果在FutureBuilder控件节点的父节点重绘rebuild,那么FutureBuilder也会重绘,这不仅耗费不必要的资源,如果是网络请求还会消耗用户的流量,这是非常糟糕的体验,如何解决这个问题?

分类:
iOS
收藏成功!
已添加到「」, 点击更改