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&lt;Absences&gt;(context).items;而不是final absences = Provider.of&lt;AbsencesTypes&gt;(context).items; @PatrickO'Hara 我在发布这个问题时忘记更改它,但我的问题已经解决了,谢谢:) 【参考方案1】:

您的问题可能是您在没有等待结果的情况下致电http.getgetAbsencesTypeshttp.get 方法执行后立即返回Future&lt;void&gt;,无需等待答案,这会导致您的onComplete 方法被触发。

一个简单的解决方法是在http.get 之前添加await 关键字,但您可以做得更好。

在您的代码中,您没有完全使用可以解决您的问题的ChangeNotifierProvider。您应该查看Consumer 课程,这对您来说非常有用,但由于这不是您最初的问题,所以我不会更深入地讨论这个主题。

【讨论】:

await 关键字解决了这个问题。我的坏 :D 谢谢!

以上是关于Flutter - 使用提供程序时 whenComplete() 无法按预期工作的主要内容,如果未能解决你的问题,请参考以下文章

使用提供程序包 FLUTTER 关闭应用程序后保存状态

flutter_bloc 库中的存储库提供程序在推送新路由时不提供存储库

Flutter:提供程序未更新 UI

Flutter - 用户从应用程序退出后如何擦除提供者数据?

将提供程序包添加到 Flutter Web 项目时出错

如何使用提供程序在 Flutter ui 中使用 api 响应获取 ListView 构建器数据