我想知道何时应该使用将来的构建器。例如,如果我要发出http请求并在列表视图中显示结果,则打开视图后,我是否必须使用future构建器或仅构建ListViewBuilder
像这样:
new ListView.builder(
itemCount: _features.length,
itemBuilder: (BuildContext context, int position) {
...stuff here...
}
此外,如果我不想构建列表视图,而是想要构建一些更复杂的东西(例如圆形图表),我是否应该使用Future Builder?
希望这很清楚!
答案 0 :(得分:13)
FutureBuilder
删除一些样板代码。
让我们说您想在页面启动时fetch data from backend
并显示加载器,直到数据到来。
ListBuilder的任务:
dataFromBackend
2。isLoadingFlag
isLoadingFlag = true
并根据显示loader
。backend
获得的数据来设置数据并设置isLoadingFlag = false
(显然在setState
内部)if-else
创建中创建一个widget
。如果isLoadingFlag
是true
,请显示loader
,否则请显示data
。如果失败,请显示error message
。FutureBuilder的任务
future
中的异步任务connectionState
,显示message
(loading
,active(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
代码,以了解使用此代码对性能的影响。
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种状态:
答案 2 :(得分:2)
FutureBuilder 是一个 Widget,可帮助您执行一些异步函数,并根据该函数的结果更新您的 UI。
我列出了一些用例,你为什么要使用 FutureBuilder?
如果您想在异步任务后呈现小部件,请使用它。
我们可以通过简单地使用 ConnectionState.waiting
不需要任何自定义错误控制器。可以简单地处理错误dataSnapshot.error != null
因为我们可以在构建器中处理异步任务,所以我们不需要任何 setState(() { _isLoading = false; });
当我们使用 FutureBuilder 小部件时,我们需要检查未来状态,即未来是否已解决等等。有多种状态如下:
ConnectionState.none:
表示future为null,initialData作为defaultValue。
ConnectionState.active:
表示未来不为空但尚未解析。
ConnectionState.waiting:
表示未来正在解决中,我们很快就会得到结果。
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]),
),
);
}
}
},
),