这一节主要介绍Flutter中异步UI更新涉及的知识。在应用层面开发中,很多时候我们会依赖一些异步数据来动态更新UI,比如在打开一个页面时我们需要先从互联网上获取数据,在获取数据的过程中我们显示一个加载框,等获取到数据时我们再渲染带有数据的页面;Flutter中FutureBuilder能够满足这种场景。
FutureBuilder会依赖一个Future,它会根据所依赖的Future的状态来动态构建自身。我们看一下FutureBuilder构造函数:
FutureBuilder({
this.future,
this.initialData,
@required this.builder,
})
future:FutureBuilder依赖的Future,通常是一个异步耗时任务。
initialData:初始数据,用户设置默认数据。
builder:Widget构建器;该构建器会在Future执行的不同阶段被多次调用,构建器签名如下:
Function (BuildContext context, AsyncSnapshot snapshot)
snapshot会包含当前异步任务的状态信息及结果信息 ,比如我们可以通过snapshot.connectionState获取异步任务的状态信息、通过snapshot.hasError判断异步任务是否有错误等等,完整的定义读者可以查看AsyncSnapshot类定义。
官方建议 它的实例尽量越早比较好,在State的initState,State.didUpdateWidget, or State.didChangeDependencies,不要在build里面去实例化。
栗子:
class _DemoState extends State {
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: downloadData(), // function where you call your api
builder: (BuildContext context, AsyncSnapshot snapshot) { // AsyncSnapshot
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 downloadData()async{
// var response = await http.get('https://getProjectList');
return Future.value("Data download successfully"); // return your response
}
}
官网:FutureBuilder
StreamBuilder控件用用最新交互流数据来构建自身 ,通常我们在开发 Flutter 页面,数据发生更新,都是直接通过 setState 方式对整个页面进行更新。如果页面某些数据需要每秒都更新,比如说下载文件时显示的进度条,对整个页面都刷新是很影响页面性能,有必要局部刷新。
栗子:
Stream _bids = (() async* {
await Future.delayed(Duration(seconds: 1));
yield 1;
await Future.delayed(Duration(seconds: 1));
})();
Widget build(BuildContext context) {
return DefaultTextStyle(
style: Theme.of(context).textTheme.headline2,
textAlign: TextAlign.center,
child: Container(
alignment: FractionalOffset.center,
color: Colors.white,
child: StreamBuilder(
stream: _bids,
builder: (BuildContext context, AsyncSnapshot snapshot) {
List children;
if (snapshot.hasError) {
children = [
Icon(
Icons.error_outline,
color: Colors.red,
size: 60,
),
Padding(
padding: const EdgeInsets.only(top: 16),
child: Text('Error: ${snapshot.error}'),
)
];
} else {
switch (snapshot.connectionState) {
case ConnectionState.none:
children = [
Icon(
Icons.info,
color: Colors.blue,
size: 60,
),
const Padding(
padding: EdgeInsets.only(top: 16),
child: Text('Select a lot'),
)
];
break;
case ConnectionState.waiting:
children = [
SizedBox(
child: const CircularProgressIndicator(),
width: 60,
height: 60,
),
const Padding(
padding: EdgeInsets.only(top: 16),
child: Text('Awaiting bids...'),
)
];
break;
case ConnectionState.active:
children = [
Icon(
Icons.check_circle_outline,
color: Colors.green,
size: 60,
),
Padding(
padding: const EdgeInsets.only(top: 16),
child: Text('\$${snapshot.data}'),
)
];
break;
case ConnectionState.done:
children = [
Icon(
Icons.info,
color: Colors.blue,
size: 60,
),
Padding(
padding: const EdgeInsets.only(top: 16),
child: Text('\$${snapshot.data} (closed)'),
)
];
break;
}
}
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: children,
);
},
),
),
);
}
官网:StreamBuilder