当页面数据未从 Firebase 完全加载时显示加载指示器/微调器 - Flutter

Posted

技术标签:

【中文标题】当页面数据未从 Firebase 完全加载时显示加载指示器/微调器 - Flutter【英文标题】:Show loading indicator /spinner when the page data isn't fully loaded from Firebase - Flutter 【发布时间】:2021-01-16 03:17:20 【问题描述】:

在我的 Flutter 应用中,当我点击表单屏幕中的保存按钮时,我使用 ModalProgressHUD 显示一个微调器,一旦数据成功写入 Firebase,它就会停止微调器。

我有这个屏幕,它使用 Listview.builder 显示我所有费用的列表,我想在页面显示后立即自动显示微调器,并在 Firebase 中的所有数据完全加载后停止微调器。

我在执行此操作时需要帮助。我已经粘贴了我的代码摘录,如下所示。提前致谢。

//class wide declaration
bool showSpinner = true;



Widget build(BuildContext context) 

ExpenseNotifier expenseNotifier = Provider.of<ExpenseNotifier>(context);


Future<void> _resfreshList() async 
  expenseNotifier.getExpenses(expenseNotifier);
  var expenseList = ExpenseNotifier.getExpenses(expenseNotifier);
  if (expenseList != null) 
    setState(() 
      showSpinner = false;
    );


    return Scaffold(
      body: ModalProgressHUD(
            inAsyncCall: showSpinner,
            child: RefreshIndicator(
              onRefresh: _resfreshList,
              child: Consumer<ExpenseNotifier>(
                builder: (context, expense, child) 
                  return expense == null
                      ? Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          crossAxisAlignment: CrossAxisAlignment.center,
                          children: <Widget>[
                            PaddingClass(bodyImage: 'images/empty.png'),
                            SizedBox(
                              height: 20.0,
                            ),
                            Text(
                              'You don\'t have any expenses',
                              style: kLabelTextStyle,
                            ),
                          ],
                        )
                      : ListView.separated(
                          itemBuilder: (context, int index) 
                            var myExpense = expense.expenseList[index];
                            return Card(
                              elevation: 8.0,
                              color: Colors.white70,
                              child: Column(
                                mainAxisAlignment: MainAxisAlignment.start,
                                children: <Widget>[
                                  RegularExpenseTextPadding(
                                    regText:
                                        '$_formattedDate(myExpense.updatedAt)',
                                  ),
                                  Container(
                                    margin: EdgeInsets.all(20.0),
                                    padding: const EdgeInsets.all(15.0),
                                    decoration: BoxDecoration(
                                      borderRadius:
                                          BorderRadius.all(Radius.circular(5.0)),
                                      border: Border.all(
                                          color: kThemeStyleBorderHighlightColour),
                                    ),
                                    child: Row(
                                      children: <Widget>[
                                        Expanded(
                                          flex: 5,
                                          child: Column(
                                            crossAxisAlignment:
                                                CrossAxisAlignment.start,
                                            children: <Widget>[
                                              Text(
                                                '$myExpense.amount',
                                                style: kRegularTextStyle,
                                              ),
                                              SizedBox(
                                                height: 20.0,
                                              ),
                                              Text(
                                                myExpense.description,
                                                style: kRegularTextStyle,
                                              ),
                                            ],
                                          ),
                                        ),
                                        Expanded(
                                          flex: 1,
                                          child: GestureDetector(
                                            onTap: () 
                                              expenseNotifier.currentExpense =
                                                  expenseNotifier
                                                      .expenseList[index];
                                              Navigator.of(context).push(
                                                  MaterialPageRoute(builder:
                                                      (BuildContext context) 
                                                return ExpenseDetailsScreen();
                                              ));
                                            ,
                                            child: Icon(
                                              FontAwesomeIcons.caretDown,
                                              color: kThemeIconColour,
                                            ),
                                          ),
                                        ),
                                      ],
                                    ),
                                  ),
                                ],
                              ),
                            );
                          ,
                          separatorBuilder: (BuildContext context, int index) 
                            return SizedBox(
                              height: 20.0,
                            );
                          ,
                          itemCount: expenseNotifier.expenseList.length,
                        );
                ,
              ),
            ),
          ),
    );
    
  

【问题讨论】:

【参考方案1】:

这是我的应用程序中的一个示例:

bool _isLoading = false; <- default false
  bool _isInit = true; <- to mae it only load once


@override
  void initState() 

if (_isInit) 
     // activating spinner
      _isLoading = true;

      // your function here <------

    _isInit = false;
    super.initState();
  

Initstate 在用户可以看到您的应用中的任何类型之前被调用,因此这是加载您的 Firebase 数据的理想场所。只要您收到数据,加载微调器就会显示上面的这个逻辑。然后你的身体看起来像下面这样:

@override
  Widget build(BuildContext context) 

    return _isLoading <- is loading condition true? shows spinner
        ? Center(child: CircularProgressIndicator()) <- loading spinner
    // else shows your content of the app
    : SafeArea(
        child: Container()
            ....

【讨论】:

嘿马塞尔,我试着模仿你上面建议的样本。我将 isLoading 的默认值设置为 true,因为我希望微调器立即显示页面加载,并在从 db 成功读取数据时将其设置为 false。但是即使页面完全加载,微调器也不会停止。我已经编辑了我的问题以包括我所做的更新。要查找更改,请检查 showSpinner 声明、inAsyncCall、_resfreshList 函数。 @hermie_brown 请检查我的代码 我更改了它,当您回复我的代码时,我刚刚注意到我从文件中提取了错误的部分。现在它是正确的,把它作为你的构造,它现在应该可以工作了。您将使用 initstate 加载它,并在加载完成后显示应用程序内容。像在我的示例中那样保持 isLoading 为 false,这样您就不会遇到麻烦

以上是关于当页面数据未从 Firebase 完全加载时显示加载指示器/微调器 - Flutter的主要内容,如果未能解决你的问题,请参考以下文章

当屏幕未从 Firebase 调用数据时如何显示文本小部件

未从 Firebase 存储加载的用户图像

从 firebase 数据库获取数据时显示进度对话框

未从 firebase 数据库中检索个人资料图片

jQuery Mobile 面板在页面完全加载之前在初始加载时显示,速度较慢的设备

javascript函数调用以获取数据并在页面加载时显示到屏幕