5、 Flutter Widgets 之 FutureBuilder
展示异步任务状态
当有一个Future(异步)任务需要展示给用户时,可以使用FutureBuilder控件来完成,比如向服务器发送数据成功时显示成功提示:
import 'package:flutter/material.dart';
class WyFutureBuilder extends StatefulWidget {
@override
_WyFutureBuilderState createState() => _WyFutureBuilderState();
}
class _WyFutureBuilderState extends State<WyFutureBuilder> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('FutureBuilder'),
),
body: _creactFutureBuilder(),
);
}
var _future = Future.delayed(Duration(seconds: 5), () {
return '老王,一个有态度的程序员';
});
Widget _creactFutureBuilder() {
return FutureBuilder(
future: _future,
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
var widget;
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
widget = Icon(
Icons.error,
color: Colors.red,
size: 48,
);
} else {
widget = Icon(
Icons.check_circle,
color: Colors.green,
size: 36,
);
}
} else {
widget = Padding(
padding: EdgeInsets.all(20),
child: CircularProgressIndicator(),
);
}
return Center(
child: Container(
height: 100,
width: 100,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.all(Radius.circular(10))),
child: widget,
),
);
});
}
}
在Future任务中出现异常如何处理,下面模拟出现异常,修改_future:
var _future = Future.delayed(Duration(seconds: 3), () {
return Future.error('');
});
builder是FutureBuilder的构建函数,在这里可以判断状态及数据显示不同的UI, ConnectionState的状态包含四种:none、waiting、active、done,但我们只需要关注done状态,此状态表示Future执行完成,snapshot参数的类型是AsyncSnapshot。
ListView加载网络数据
FutureBuilder还有一个比较常用的场景:网络加载数据并列表展示,这是一个非常常见的功能,在网络请求过程中显示loading,请求失败时显示失败UI,成功时显示成功UI。
模拟成功网络请求,通常会返回json字符串:
var _future = Future.delayed(Duration(seconds: 3), () {
return 'json 字符串';
});
//构建FutureBuilder控件:
Widget _createListView(){
return FutureBuilder(
future: _future,
builder: (context, snapshot) {
var widget;
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
widget = _loadingErrorWidget();
} else {
widget = _dataWidget(snapshot.data);
}
} else {
widget = _loadingWidget();
}
return widget;
});
}
//构建loading控件:
_loadingWidget(){
return Center(
child: Padding(
padding: EdgeInsets.all(20),
child: CircularProgressIndicator(),
),
);
}
//数据加载成功,构建数据展示控件:
_dataWidget(data){
return ListView.separated(itemBuilder: (context,index){
return Container(
height: 60,
alignment: Alignment.center,
child: Text('$index',style: TextStyle(fontSize: 20),),
);
},
separatorBuilder: (context,index){
return Divider();
},
itemCount: 10);
}
//构建网络加载失败控件:
_loadingErrorWidget() {
return Center(
child: Text('数据加载失败,请重试。'),
);
}
模拟网络加载失败:
var _future = Future.delayed(Duration(seconds: 3), () {
return Future.error('');
});
通过上面的示例说明FutureBuilder控件极大的简化了异步任务相关显示的控件,不再需要开发者自己维护各种状态以及更新时调用State.setState
。
防止FutureBuilder重绘
FutureBuilder是一个StatefulWidget控件,如果在FutureBuilder控件节点的父节点重绘rebuild
,那么FutureBuilder也会重绘,这不仅耗费不必要的资源,如果是网络请求还会消耗用户的流量,这是非常糟糕的体验,如何解决这个问题?
转载自:https://juejin.cn/post/7149582870875471879