Flutter FutureBuilder 优雅地构建了异步用户界面
在实际开发中,一般需要在显示列表内容之前显示loading
。这意味着它正在加载。上传成功后,会显示列表内容。如果加载失败,会显示失败的界面
所以,这样的请求会涉及三种情况:
- 正在加载
- 加载成功显示列表
- 加载失败,显示错误
我们知道Flutter UI
是一个声明式UI
当你在不同的UI之间切换时,它是通过setState
重建的。因此,对于上面三个用户界面的例子,我们需要使用if else
来判断显示哪个界面。。需要维护很多变量,非常不优雅。管理
builder
根据异步任务状态构建不同的 Widget
与上面类似 if/else
FutureBuilder
,异步任务状态为:
状态 | 描述 |
---|---|
n | 未连接到任何异步任务 |
waiti ng | 已连接到等待交互的异步任务 |
活动 | 连接到激活的异步任务 |
done | 与已完成的异步任务相关联 |
为了改造上面的例子,我们可以使用FutureBuilder
,代码如下:
FutureBuilder<int>(
future: _loadList(),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
case ConnectionState.active:
// 显示正在加载
return createLoadingWidget();
case ConnectionState.done:
// 提示错误信息
if (snapshot.hasError) {
return createErrorWidget(snapshot.error.toString());
}
// 展示列表内容
return ListView.separated(
itemCount: snapshot.data,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text(index.toString()));
},
separatorBuilder: (BuildContext context, int index) {
return divider;
},
);
default:
return Text("unknown state");
)
复制代码
需要注意的是,上面的代码接口每个time 重建时会执行loadList操作。
不过,有时候界面改变时,不需要重做未来
。比如界面是Tab + ListView(文章类别+文章列表)
,必须先加载文章分类,然后文章分类的异步任务是future
。分类加载成功后,即可加载项目列表。当列表加载成功后,界面将被重建。这次,文章类别(未来)
无法重新加载。目前需要将变量future
作为成员变量,在initState
中初始化,然后传递给future
参数,如:
Future _future;
@override
void initState() {
_future = _loadList();
super.initState();
}
FutureBuilder<int>(
future: _future,
...
)
复制代码
执行效果如下图:
FutureBuilder源码分析
FutureBuilder
继承了StatefulWidget
,所以主要代码集中在State
除了StreamBuilder
中的
FutureBuilder
可以优雅地构建异步UI之外,还可以实现StreamBuilder
,但一般来说,作为一个UI的展示同步任务,它不是一个 Stream
Stream 的形式,更像是一次性的逻辑处理。只要成功,一般不需要更新,所以使用FutureBuilder
就完全足够了。实际开发中,根据情况进行选择。 StreamBuilder
功能更强大。如果以后向stream
发送数据,用户界面也会相应改变。例如:
StreamBuilder<int>(
// 这个是stream 而不是 future
stream: _streamController.stream,
initialData: _counter,
builder: (BuildContext context, AsyncSnapshot<int> snapshot){
// 接收到 controller 发送给 stream 的数据
return Text('${snapshot.data}');
}
),
)
复制代码
我们可以通过
_streamController
发送数据,那么就会被自动调用。 StreamBuilder 构建器
Widget
_streamController.sink.add(++_counter);
复制代码
的回调。当然,也可以提供 stream 而不传递
StreamController
,或者您也可以创建一个返回 的函数流动。
作者:Chiclaim
来源:掘金
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。