flutter - Flutter - 在 FutureBuilder 中使用 RefreshIndicator 拉动刷新
问题描述
编辑:最小的可重现示例。请查看 中的刷新方法main.dart
。
我正在使用 aFutureBuilder
来显示网络请求的结果。我调用我的 fetch 方法initstate
(就像这里建议的那样):
Future<List<CheckIn>> futureCheckIn;
@override
void initState() {
super.initState();
_eventArg = Provider.of<EventArg>(context, listen: false);
_helper = ApiHelper(context);
futureCheckIn = _helper.fetchCheckIns(_eventArg.getEvent().id.toString());
}
我现在想使用 aRefreshIndicator
来允许用户刷新屏幕。在我的网络请求以异常结束(例如 404)之前,这很有效。通常异常会被捕获,FutureBuilder
但在执行后异常中的请求RefreshIndicator
未处理......
这是我的代码:
RefreshIndicator buildResult(List<CheckIn> checkIns, BuildContext context) {
return RefreshIndicator(
key: _refreshKey,
onRefresh: () async {
setState(() {});
futureCheckIn =
_helper.fetchCheckIns(_eventArg.getEvent().id.toString()); // this could end with an exception
},
child: Container(
height: MediaQuery.of(context).size.height,
child: SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(),
scrollDirection: Axis.vertical,
child: Column(
children: [
Container(
margin: EdgeInsets.all(10),
child: Text(
constants.CHECK_IN_SCREEN_DESCRIPTION,
style: TextStyle(fontSize: 16),
textAlign: TextAlign.justify,
),
),
ListView(
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
scrollDirection: Axis.vertical,
shrinkWrap: true,
children: checkIns.map((el) {
return Card(
elevation: 4,
child: ListTile(
title: Text(el.name),
onTap: () async {
...
},
trailing: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.arrow_forward_ios,
color: Colors.black,
)
],
),
),
);
}).toList(),
)
],
),
),
),
);
}
如何RefreshIndicator
正确使用 with FutureBuilder
?
编辑@Shri Hari:抛出此异常
class AppException implements Exception {
final _message;
final _prefix;
AppException([this._message, this._prefix]);
String toString() {
return "$_prefix$_message";
}
}
class NotFoundException extends AppException {
NotFoundException([String message]) : super(message, "Data not found: ");
}
编辑@Mhark Batoctoy:是的,它是以下内容的一部分FutureBuilder
:
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: futureCheckIn,
builder: (context, snapshot) {
if (snapshot.hasData) {
List<CheckIn> checkIns = snapshot.data;
return buildResult(checkIns, context); // RefreshIndicator is nested in here
} else if (snapshot.hasError) {
// Error handling
...
}
// Spinner während der Datenabfrage
return Center(
child: CircularProgressIndicator(),
);
},
);
不幸地将onRefresh
-Method 从
onRefresh: () async {
setState(() {});
futureCheckIn =
_helper.fetchCheckIns(_eventArg.getEvent().id.toString()); // this could end with an exception
},
至
onRefresh: () async {
setState(() {});
return futureCheckIn =
_helper.fetchCheckIns(_eventArg.getEvent().id.toString()); // this could end with an exception
},
或者
onRefresh: () async {
setState(() {});
return _helper.fetchCheckIns(_eventArg.getEvent().id.toString()); // this could end with an exception
},
不改变错误...
解决方案
不确定这是否是最好的答案,但我遇到了同样的问题,必须继续前进。所以,这就是我学到和做到的。
RefreshIndicator
不喜欢例外。即使在将它们移到try / catch
or下onError
并成功使用异常之后,RefreshIndicator
仍然会为未处理的异常而哭泣(有点奇怪,但我将不得不对其进行更多调查)。
我所做的是确保我的 API 调用不会引发任何异常。这意味着,API 调用本身(在本例中为fetchCheckIns()
函数调用)捕获所有类型的已知/未知异常 [ catch (e)
],并在您从 API 返回的响应对象中设置一个标志(在本例中为返回类型对象fetchCheckIns()
)。
现在,在您FutureBuilder
调用 时buildResult(checkIns, context)
,检查snapshot.data
并查找任何失败标志。如果失败,请以不同的方式渲染屏幕。那是:
if (snapshot.hasData) {
if (snapshot.data.error == true) {
return ...; // Render error message
} else {
return buildResult(snapshot.data, context);
}
}
这也意味着,您可能无法返回对象列表,并且可能必须将其包装在将包含对象列表的单个对象中。
意味着,你的CheckIn
对象可能被包裹着类似的东西
class AllCheckIn {
List<CheckIn> checkIns;
bool error;
String errorMsg;
}
或者,您还可以根据您在 API 调用中接收和捕获的异常添加更多错误消息描述,并在FutureBuilder
.
希望这会有所帮助。
推荐阅读
- android - 仅当用户单击 searchView 时才打开键盘
- spring - Spring Boot:位于子目录中时未加载 application-{profile}.yml
- azure-ad-b2c - 如何在 Azure B2C 中显示 REST 错误消息
- winapi - 如何在 VB6 中定义 POWERBROADCAST_SETTING?
- c++ - 在多个参数包上同时递归
- r - 映射列表并根据列 ID 提取数据框
- po - 当我运行 django-admin 编译消息时,我的 po 文件与翻译显示一些错误
- node.js - node.js 中的 POST 请求后如何输出变量?
- three.js - SSR 和 SSAO 不能一起使用
- python - 无法在snakemake中执行shell脚本