FLutter入门:异步加载组件FutureBuilder

Posted BennuCTech

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FLutter入门:异步加载组件FutureBuilder相关的知识,希望对你有一定的参考价值。

FutureBuilder

在实际开发中,进入一个页面后执行网络请求加载数据并显示是非常普遍的,这时候我们一般会显示loading直到加载完成显示正常页面。在flutter中我们可以在initState中发起异步请求,然后将请求结果赋值给data,并setState刷新页面,在build中可以这样实现

if(data == null)
    return _LoadingWidget()

else
    return ...

实际上flutter提供了一个FutureBuilder专门来处理需要异步的组件,下面是一个简单的示例:

var _future = Future.delayed(Duration(seconds: 3), () 
    return '服务器返回的数据';
  );
 
FutureBuilder(
      future: _future,
      builder: (context, snapshot) 
        var widget;
        if (snapshot.connectionState == ConnectionState.done) 
          if (snapshot.hasError) 
            widget = Text("出错了");
           else 
            widget = Text(snapshot.data);
          
         else 
          widget = Padding(
            padding: EdgeInsets.all(20),
            child: CircularProgressIndicator(),
          );
        
 
        return Center(
          child: widget,
        );
      ,
    );

可以看到FutureBuilder有两个主要属性

  • future:异步处理的任务。比如请求数据,读取文件等等
  • builder:创建widget。其中它的snapshot是该组件当前的状态,我们通过它来实现组件的切换。

snapshot的connectionState表示异步任务的状态,如果是ConnectionState.done表示任务完成,这时候通过snapshot.hasError来区分是出错(显示错误)还是正常完成(显示数据);否则就表示任务在执行中(显示laoding)。我们通过这些状态来返回不同的组件来实现异步加载的过程。

当任务正常完成(ConnectionState.done且snapshot.hasError为false)时,我们可以通过snapshot.data来获取异步返回的数据,再渲染页面即可。

防止FutureBuilder重绘

FutureBuilder是一个StatefulWidget控件,如果父节点重绘rebuild那么FutureBuilder也会重绘,但是这时候可能我们根本不是要请求数据,可能仅仅是更新页面上的一个文案,这样就会造成不必要的浪费和消耗,我们要尽量避免,所以就需要防止FutureBuilder重绘。

FutureBuilder重绘源码如下:

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

可以看到它是判断futrue是否是同一个对象来执行重绘的,所以我们只要提前将异步任务的函数赋值给一个变量,然后在FutureBuilder中使用这个变量即可,如下:

var _mFuture;
 
  @override
  void initState() 
    // TODO: implement initState
    super.initState();
    _mFuture = _future();
  
 
 _future() async
    ...
  
 
FutureBuilder(
    future: _mFuture,
    ...
)

有人提到直接将函数赋值是否可以达到同样的效果,比如:

 _future() async
    ...
  
 
FutureBuilder(
    future: _future(),
    ...
)

根据网友的总结,是不可以的。待验证。

关注公众号:BennuCTech,获取更多干货!

以上是关于FLutter入门:异步加载组件FutureBuilder的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 功能型组件:异步UI更新(FutureBuilderStreamBuilder)

Vuex入门同步异步 存取值

Flutter入门(二)——实现一个简单的demo页面

Flutter 异步加载多个函数一个接一个

如何从flutter中从异步任务中检索到的数据中将图像加载到卡片中?

Flutter 专题15 图解 ListView 异步加载数据与等待 #yyds干货盘点#