Flutter - 使用提供程序时 whenComplete() 无法按预期工作
Posted
技术标签:
【中文标题】Flutter - 使用提供程序时 whenComplete() 无法按预期工作【英文标题】:Flutter - whenComplete() not working as expected when using Providers 【发布时间】:2021-06-27 17:36:23 【问题描述】:我正在尝试在执行 API 请求时显示加载,并在完成时显示带有响应的列表或自定义小部件以显示消息 (EmptyListWidget)。问题是 whenComplete() 方法是在异步函数完成之前执行的。
我也尝试使用 then() 和 FutureBuilder,但我也无法使用 Provider 使其工作(总是返回 null)。
如果有人可以提供帮助,我将不胜感激。谢谢 :)
我的列表小部件:
class _AbsencesListState extends State<AbsencesList>
bool _isLoading = false;
bool _isInit = true;
@override
void didChangeDependencies()
super.didChangeDependencies();
if (_isInit)
setState(() => _isLoading = true);
Provider.of<AbsencesTypes>(context, listen: false)
.getAbsencesTypes(widget.ctx)
.whenComplete(()
setState(() => _isLoading = false);
);
_isInit = false;
@override
Widget build(BuildContext context)
final absences = Provider.of<Absences>(context).items;
return Stack(
children: [
_isLoading
? const Center(child: CircularProgressIndicator())
: absences.length > 0
? Container()
: EmptyListWidget(ListType.InconsistenciesList),
ListView.builder(
itemBuilder: (_, index)
return GestureDetector(
onTap: () ,
child: Card(
elevation: 2.0,
child: ListTile(
leading: CircleAvatar(
child: const Icon(Icons.sick),
backgroundColor: Theme.of(context).accentColor,
foregroundColor: Colors.white,
),
title: Padding(
padding: const EdgeInsets.only(top: 3),
child: Text(absences[index].absenceType.name),
),
subtitle: Text(
absences[index].firstDate
),
),
),
);
,
itemCount: absences.length,
)
],
);
异步函数:
class AbsencesTypes with ChangeNotifier
List<AbsenceType> _absencesTypesList = [];
List<AbsenceType> get items
return [..._absencesTypesList];
void emptyAbsencesTypeList()
_absencesTypesList.clear();
Future<void> getAbsencesTypes(BuildContext context) async
SharedPreferences _prefs = await SharedPreferences.getInstance();
String token = _prefs.getString(TOKEN_KEY);
http.get(
API_URL,
headers: "Authorization": token,
).then(
(http.Response response) async
if (response.statusCode == 200)
final apiResponse = json.decode(utf8.decode(response.bodyBytes));
final extractedData = apiResponse['content'];
final List<AbsenceType> loadedAbsencesTypes = [];
for (var absenceType in extractedData)
loadedAbsencesTypes.add(
AbsenceType(
id: absenceType["id"],
name: absenceType["name"].toString(),
code: absenceType["code"].toString(),
totalAllowedDays: absenceType["totalAllowedDays"],
),
);
_absencesTypesList = loadedAbsencesTypes;
else if (response.statusCode == 401)
Utility.showToast(
AppLocalizations.of(context).translate("expired_session_string"));
Utility.sendUserToLogin(_prefs, context);
notifyListeners();
,
);
【问题讨论】:
为什么你有final absences = Provider.of<Absences>(context).items;
而不是final absences = Provider.of<AbsencesTypes>(context).items;
?
@PatrickO'Hara 我在发布这个问题时忘记更改它,但我的问题已经解决了,谢谢:)
【参考方案1】:
您的问题可能是您在没有等待结果的情况下致电http.get
。getAbsencesTypes
在http.get
方法执行后立即返回Future<void>
,无需等待答案,这会导致您的onComplete
方法被触发。
一个简单的解决方法是在http.get
之前添加await
关键字,但您可以做得更好。
在您的代码中,您没有完全使用可以解决您的问题的ChangeNotifierProvider
。您应该查看Consumer 课程,这对您来说非常有用,但由于这不是您最初的问题,所以我不会更深入地讨论这个主题。
【讨论】:
await
关键字解决了这个问题。我的坏 :D 谢谢!以上是关于Flutter - 使用提供程序时 whenComplete() 无法按预期工作的主要内容,如果未能解决你的问题,请参考以下文章
flutter_bloc 库中的存储库提供程序在推送新路由时不提供存储库