Flutter-未来的建设者:我什么时候应该使用它

时间:2018-08-23 09:52:48

标签: dart flutter future builder

我想知道何时应该使用将来的构建器。例如,如果我要发出http请求并在列表视图中显示结果,则打开视图后,我是否必须使用future构建器或仅构建ListViewBuilder像这样:

new ListView.builder(
        itemCount: _features.length,
        itemBuilder: (BuildContext context, int position) {
...stuff here...
}

此外,如果我不想构建列表视图,而是想要构建一些更复杂的东西(例如圆形图表),我是否应该使用Future Builder?

希望这很清楚!

3 个答案:

答案 0 :(得分:13)

FutureBuilder 删除一些样板代码

让我们说您想在页面启动时fetch data from backend并显示加载器,直到数据到来。

ListBuilder的任务:

  • 具有两个状态变量1。dataFromBackend 2。isLoadingFlag
  • 启动时,设置isLoadingFlag = true并根据显示loader
  • 数据到达后,使用您从backend获得的数据来设置数据并设置isLoadingFlag = false(显然在setState内部)
  • 我们需要在if-else创建中创建一个widget。如果isLoadingFlagtrue,请显示loader,否则请显示data。如果失败,请显示error message

FutureBuilder的任务

  • 给予Future Builder future中的异步任务
  • 基于connectionState,显示messageloadingactive(streams)done
  • 基于data(snapshot.hasError)的展示视图

FutureBuilder的优点

  • 没有two flags也没有setState
  • 反应性编程(FutureBuilder将负责更新有关数据到达的视图)

示例:

    new FutureBuilder<String>(
        future: _fetchNetworkCall, // async work
        builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
           switch (snapshot.connectionState) {
             case ConnectionState.waiting: return new Text('Loading....');
             default:
               if (snapshot.hasError)
                  return new Text('Error: ${snapshot.error}');
               else
              return new Text('Result: ${snapshot.data}');
            }
         },
        )

性能影响:

我只是研究了FutureBuilder代码,以了解使用此代码对性能的影响。

  • FutureBuilder只是一个StatefulWidget变量为state的{​​{1}}
  • 初始状态为_snapshot
  • 它正在订阅_snapshot = new AsyncSnapshot<T>.withData(ConnectionState.none, widget.initialData);,我们将其发送到构造函数中,并根据该更新来更新future

    state

因此widget.future.then<void>((T data) { if (_activeCallbackIdentity == callbackIdentity) { setState(() { _snapshot = new AsyncSnapshot<T>.withData(ConnectionState.done, data); }); } }, onError: (Object error) { if (_activeCallbackIdentity == callbackIdentity) { setState(() { _snapshot = new AsyncSnapshot<T>.withError(ConnectionState.done, error); }); } }); 是我们通常所做工作的包装/样板。因此,不应有任何性能影响。

答案 1 :(得分:2)

FutureBuilder示例

  • 当您要在异步调用后对窗口小部件进行标记时,请使用 FutureBuilder()

    class _DemoState extends State<Demo> {
    
    @override
    Widget build(BuildContext context) {
      return FutureBuilder<String>(
        future: downloadData(), // function where you call your api
        builder: (BuildContext context, AsyncSnapshot<String> snapshot) {  // AsyncSnapshot<Your object type>
          if( snapshot.connectionState == ConnectionState.waiting){
              return  Center(child: Text('Please wait its loading...'));
          }else{
              if (snapshot.hasError)
                return Center(child: Text('Error: ${snapshot.error}'));
              else
                return Center(child: new Text('${snapshot.data}'));  // snapshot.data  :- get your object which is pass from your downloadData() function
          }
        },
      );
    }
    Future<String> downloadData()async{
      //   var response =  await http.get('https://getProjectList');    
      return Future.value("Data download successfully"); // return your response
    }
    }
    

在future构建器中,它调用future函数来等待结果,并在生成结果后立即调用构建器函数来构建小部件。

AsyncSnapshot具有3种状态:

  1. connectionState.none =在此状态下,将来为空

  2. connectionState.waiting = [未来]不为空,但尚未完成

  3. connectionState.done = [未来]不为空,并且已完成。如果将来成功完成,则[AsyncSnapshot.data]将设置为将来完成的值。如果完成并出现错误,则[AsyncSnapshot.hasError]为true

答案 2 :(得分:2)

FutureBuilder 是一个 Widget,可帮助您执行一些异步函数,并根据该函数的结果更新您的 UI。

我列出了一些用例,你为什么要使用 FutureBuilder?

  1. 如果您想在异步任务后呈现小部件,请使用它。

  2. 我们可以通过简单地使用 ConnectionState.waiting

    来处理加载过程
  3. 不需要任何自定义错误控制器。可以简单地处理错误dataSnapshot.error != null

  4. 因为我们可以在构建器中处理异步任务,所以我们不需要任何 setState(() { _isLoading = false; });

当我们使用 FutureBuilder 小部件时,我们需要检查未来状态,即未来是否已解决等等。有多种状态如下:

  1. ConnectionState.none: 表示future为null,initialData作为defaultValue。

  2. ConnectionState.active: 表示未来不为空但尚未解析。

  3. ConnectionState.waiting: 表示未来正在解决中,我们很快就会得到结果。

  4. ConnectionState.done: 表示未来已解决。

一个简单的实现

这里的 OrdersProvider 是一个提供者类,而 fetchAndSetOrders() 是该提供者类的方法。

body: FutureBuilder(
        future: Provider.of<OrdersProvider>(context, listen: false)
            .fetchAndSetOrders(),
        builder: (context, dataSnapshot) {
          if (dataSnapshot.connectionState == ConnectionState.waiting) {
            return Center(
              child: CircularProgressIndicator(),
            );
          } else {
            if (dataSnapshot.error != null) {
              return Center(
                child: Text('An error occured'),
              );
            } else {
              return Consumer<OrdersProvider>(
                builder: (context, orderData, child) => ListView.builder(
                  itemCount: orderData.orders.length,
                  itemBuilder: (context, i) => OrderItem(orderData.orders[i]),
                ),
              );
            }
          }
        },
      ),