AsyncBuilder介紹
AsyncBuilder名字起得有點(diǎn)怪,實(shí)際上它是一個(gè)Widget控件[官方文檔],它把異步操作與數(shù)據(jù)更新結(jié)合在一起,舉個(gè)例子,以首頁為例,通常顯示首頁的時(shí)候會(huì)先判斷首頁數(shù)據(jù)拉取下來了沒,沒有沒有就顯示loading,如果有就直接渲染首頁數(shù)據(jù),代碼邏輯大概是這樣
if (data == null) {
fetchData();
showLoading();
} else {
showMainPage();
hideLoading();
}
可以看出來數(shù)據(jù)的獲取跟ui的更新都是分開的,而AsyncBuilder正是把數(shù)據(jù)獲取與數(shù)據(jù)ui更新綁定在一起,在使用AsyncBuilder時(shí)我們只需要給它傳遞一個(gè)Future對(duì)象,負(fù)責(zé)數(shù)據(jù)的獲取,以及實(shí)現(xiàn)一個(gè)AsyncWidgetBuilder回調(diào)方法,負(fù)責(zé)對(duì)應(yīng)ui的創(chuàng)建顯示即可,下面具體說說它的用法。
AsyncBuilder使用介紹
- 構(gòu)造方法
FutureBuilder({Key key, Future<T> future, T initialData, @required AsyncWidgetBuilder<T> builder })
future : 異步io操作的Future對(duì)象
initialData : 默認(rèn)初始化數(shù)據(jù)
builder : 負(fù)責(zé)根據(jù)不同狀態(tài)創(chuàng)建對(duì)應(yīng)ui的方法實(shí)現(xiàn)
Future對(duì)象
future對(duì)象的創(chuàng)建必須要提前,譬如可以在 State.initState State.didUpdateConfig, 或者 State.didChangeDependencies等時(shí)期創(chuàng)建,不能在State.build 或者StatelessWidget.build回調(diào)時(shí)去創(chuàng)建,如果在創(chuàng)建FutureBuilder時(shí)同時(shí)創(chuàng)建Future,那么一旦FutureBuilder的parent Widget發(fā)生變化時(shí),異步任務(wù)都會(huì)被觸發(fā)。AsyncWidgetBuilder 方法
AsyncWidgetBuilder是接受兩個(gè)參數(shù)BuildContext context跟AsyncSnapshot<T> snapshot并且返回一個(gè)Widget對(duì)象的方法,其中AsyncSnapshot<T> snapshot包含了異步io操作的一些信息回調(diào),其中有:
1connectionState:枚舉對(duì)象,它的值可以是nonewaitingactivedone
2data:異步io處理完時(shí)回調(diào)的數(shù)據(jù)
3error:異步io處理發(fā)生錯(cuò)誤時(shí)回調(diào)
完整例子
下面給出一個(gè)完整的代碼例子,啟動(dòng)頁面的時(shí)候會(huì)先顯示Awaiting的狀態(tài),同時(shí)會(huì)去請(qǐng)求百度的頁面,請(qǐng)求回來了就打印下數(shù)據(jù)
import 'package:flutter/material.dart';
import 'dart:io';
import 'dart:convert';
/**
* Created by nls on 2019/7/20.
* Nothing.
*/
class FutureBuilderDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(primaryColor: Colors.blue),
home: HomeWidget());
}
}
class HomeWidget extends StatefulWidget {
@override
State createState() {
return HomeState();
}
}
class HomeState extends State<HomeWidget> {
var futureFetchData;
@override
void initState() {
super.initState();
futureFetchData = fetchData();
}
Future<String> fetchData() async {
var httpClient = new HttpClient();
var uri = Uri.parse('http://www.baidu.com');
var request = await httpClient.getUrl(uri);
var response = await request.close();
var responseBody = await response.transform(utf8.decoder).join();
return responseBody;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("futureBuilder")),
body: Container(
padding: const EdgeInsets.all(10),
child: FutureBuilder<String>(
future: futureFetchData, // a previously-obtained Future<String> or null
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('Press button to start.');
case ConnectionState.active:
case ConnectionState.waiting:
return Text('Awaiting result...');
case ConnectionState.done:
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
return Text('Result: ${snapshot.data}');
}
return null; // unreachable
},
),
)
);
}
}