我什么时候应该使用FutureBuilder?



我想知道什么时候应该使用未来的构建器。例如,如果我想发出 http 请求并在列表视图中显示结果,那么一旦打开视图,我应该使用 future 构建器还是只构建一个ListViewBuilder,例如:

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

此外,如果我不想构建列表视图,而是构建一些更复杂的东西,如圆形图表,我是否应该使用未来的构建器?

希望它足够清楚!

FutureBuilder删除样板代码。

假设您想在页面启动时从后端获取一些数据并显示加载器,直到数据出现。

列表生成器的任务:

  • 有两个状态变量,dataFromBackendisLoadingFlag
  • 启动时,设置isLoadingFlag = true,并在此基础上显示loader
  • 数据到达后,使用从后端获取的数据设置数据并设置isLoadingFlag = false(显然setState内部(
  • 我们需要在小部件创建中有一个if-else。如果isLoadingFlagtrue,则显示loader否则显示data。失败时,显示错误消息。

未来建设者的任务:

  • future未来构建器中提供异步任务
  • 基于connectionState,显示消息(loadingactive(streams)done(
  • 基于data(snapshot.hasError), 显示视图

未来建设者的优点

  • 不使用两个状态变量和setState
  • 响应式编程(FutureBuilder将负责在数据到达时更新视图(

例:

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

性能影响:

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

  • FutureBuilder只是一个StatefulWidget,其state变量是_snapshot
  • 初始状态为_snapshot = AsyncSnapshot<T>.withData(ConnectionState.none, widget.initialData);
  • 它订阅了我们通过构造函数发送的future并在此基础上更新state

例:

widget.future.then<void>((T data) {
if (_activeCallbackIdentity == callbackIdentity) {
setState(() {
_snapshot = AsyncSnapshot<T>.withData(ConnectionState.done, data);
});
}
}, onError: (Object error) {
if (_activeCallbackIdentity == callbackIdentity) {
setState(() {
_snapshot = AsyncSnapshot<T>.withError(ConnectionState.done, error);
});
}
});

因此,FutureBuilder是我们通常所做的事情的包装器/样板,因此不应有任何性能影响

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 builder 中,它调用future 函数来等待结果,一旦它产生结果,它就会调用我们构建小部件的构建器函数。

异步快照有 3 种状态:

  1. 连接状态.none= 在此状态下,未来为空

  2. connectionState.wait= [future] 不为空,但尚未完成

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

FutureBuilder是一个小部件,它将帮助您执行一些异步函数,并根据该函数的结果更新您的UI。

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

  1. 如果要在异步任务后渲染小部件,请使用它。

  2. 我们可以通过简单地使用ConnectionState.waiting来处理加载过程

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

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

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

  1. ConnectionState.none:表示未来为空,初始数据用作默认值。

  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]),
),
);
}
}
},
),

相关内容

  • 没有找到相关文章

最新更新