W3Cschool
恭喜您成為首批注冊用戶
獲得88經驗值獎勵
很多時候我們會依賴一些異步數據來動態(tài)更新 UI,比如在打開一個頁面時我們需要先從互聯(lián)網上獲取數據,在獲取數據的過程中我們顯示一個加載框,等獲取到數據時我們再渲染頁面;又比如我們想展示 Stream(比如文件流、互聯(lián)網數據接收流)的進度。當然,通過 StatefulWidget 我們完全可以實現上述這些功能。但由于在實際開發(fā)中依賴異步數據更新 UI 的這種場景非常常見,因此 Flutter 專門提供了FutureBuilder
和StreamBuilder
兩個組件來快速實現這種功能。
FutureBuilder
會依賴一個Future
,它會根據所依賴的Future
的狀態(tài)來動態(tài)構建自身。我們看一下FutureBuilder
構造函數:
FutureBuilder({
this.future,
this.initialData,
@required this.builder,
})
future
:FutureBuilder
依賴的Future
,通常是一個異步耗時任務。initialData
:初始數據,用戶設置默認數據。builder
:Widget 構建器;該構建器會在Future
執(zhí)行的不同階段被多次調用,構建器簽名如下: Function (BuildContext context, AsyncSnapshot snapshot)
snapshot
會包含當前異步任務的狀態(tài)信息及結果信息 ,比如我們可以通過snapshot.connectionState
獲取異步任務的狀態(tài)信息、通過snapshot.hasError
判斷異步任務是否有錯誤等等,完整的定義讀者可以查看AsyncSnapshot
類定義。
另外,FutureBuilder
的builder
函數簽名和StreamBuilder
的builder
是相同的。
我們實現一個路由,當該路由打開時我們從網上獲取數據,獲取數據時彈一個加載框;獲取結束時,如果成功則顯示獲取到的數據,如果失敗則顯示錯誤。由于我們還沒有介紹在 flutter 中如何發(fā)起網絡請求,所以在這里我們不真正去網絡請求數據,而是模擬一下這個過程,隔3秒后返回一個字符串:
Future<String> mockNetworkData() async {
return Future.delayed(Duration(seconds: 2), () => "我是從互聯(lián)網上獲取的數據");
}
FutureBuilder
使用代碼如下:
...
Widget build(BuildContext context) {
return Center(
child: FutureBuilder<String>(
future: mockNetworkData(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
// 請求已結束
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
// 請求失敗,顯示錯誤
return Text("Error: ${snapshot.error}");
} else {
// 請求成功,顯示數據
return Text("Contents: ${snapshot.data}");
}
} else {
// 請求未結束,顯示loading
return CircularProgressIndicator();
}
},
),
);
}
運行結果如圖7-8、7-9所示:
上面代碼中我們在builder
中根據當前異步任務狀態(tài)ConnectionState
來返回不同的 widget。ConnectionState
是一個枚舉類,定義如下:
enum ConnectionState {
/// 當前沒有異步任務,比如[FutureBuilder]的[future]為null時
none,
/// 異步任務處于等待狀態(tài)
waiting,
/// Stream處于激活狀態(tài)(流上已經有數據傳遞了),對于FutureBuilder沒有該狀態(tài)。
active,
/// 異步任務已經終止.
done,
}
注意,ConnectionState.active
只在StreamBuilder
中才會出現。
我們知道,在 Dart 中Stream
也是用于接收異步事件數據,和Future
不同的是,它可以接收多個異步操作的結果,它常用于會多次讀取數據的異步任務場景,如網絡內容下載、文件讀寫等。StreamBuilder
正是用于配合Stream
來展示流上事件(數據)變化的 UI 組件。下面看一下StreamBuilder
的默認構造函數:
StreamBuilder({
Key key,
this.initialData,
Stream<T> stream,
@required this.builder,
})
可以看到和FutureBuilder
的構造函數只有一點不同:前者需要一個future
,而后者需要一個stream
。
我們創(chuàng)建一個計時器的示例:每隔1秒,計數加1。這里,我們使用Stream
來實現每隔一秒生成一個數字:
Stream<int> counter() {
return Stream.periodic(Duration(seconds: 1), (i) {
return i;
});
}
StreamBuilder
使用代碼如下:
Widget build(BuildContext context) {
return StreamBuilder<int>(
stream: counter(), //
//initialData: ,// a Stream<int> or null
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('沒有Stream');
case ConnectionState.waiting:
return Text('等待數據...');
case ConnectionState.active:
return Text('active: ${snapshot.data}');
case ConnectionState.done:
return Text('Stream已關閉');
}
return null; // unreachable
},
);
}
讀者可以自己運行本示例查看運行結果。注意,本示例只是為了演示StreamBuilder
的使用,在實戰(zhàn)中,凡是 UI 會依賴多個異步數據而發(fā)生變化的場景都可以使用StreamBuilder
。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: