【问题标题】:Flutter - How to complete/await function execution before build method?Flutter - 如何在构建方法之前完成/等待函数执行?
【发布时间】:2022-01-20 03:11:17
【问题描述】:

我只是想在这个函数中设置一个 ID:

      _getLastWorkoutId() async {
    
    try {
      var snapshot = await usersRef
          .doc(currentUser!.uid)
          .collection('workouts')
          .orderBy('workoutDate', descending: true)
          .limit(1)
          .snapshots()
          .first; 
    //The execution moves to build method from here------and then returns
      for (var element in snapshot.docs) {
        workoutId = element.id;
        setState(() {
          _isWorkoutIdSet = true;
        });
      }
      //return snapshot;
    } catch (e) {
      print(e.toString());
    }
    //return null;
  }

我在 initState 中调用它:

    @override
void initState() {
  WidgetsBinding.instance!.addObserver(this);
  super.initState();
  //var snapshot = _getLastWorkoutId();
  _getLastWorkoutId();
}

问题是,for循环是在调用build函数之后执行的。我不希望这种情况发生。

【问题讨论】:

  • 我试过了,但它需要返回一些东西,我不确定它会如何工作,因为我没有返回任何东西。
  • 我认为这不应该那么困难,因为即使是对函数的同步调用也应该有效。

标签: flutter dart async-await


【解决方案1】:

你应该声明一个变量来保存状态。例如

var isLoading = true;

在函数 _getLastWorkoutId 中的 try 块结束时,将 isLoading 重置为 false。 然后通过更好的方式调用 setState 或更新状态,使用状态管理,如 provider、bloc、get。 在构建小部件中添加检查 isLoading 像这样

return isLoading ? YourLoadingIndicatorWidget() : DisplayDataWidget();

【讨论】:

    【解决方案2】:

    我相信这应该可以解决问题:

    首先,关于构建方法:

    return FutureBuilder(
      future: _getLastWorkoutId(),
      builder: (context, snapshot) {
        if (snapshot.connectionState != ConnectionState.done) return CircularProgressIndicator();
        return Container(); // here goes whatever it is you had before.
      }
    );
    

    然后在_getLastWorkoutId():

    Future<void> _getLastWorkoutId() async {
      ...
    }
    

    这样,函数返回 void 而不是 void 的未来,允许 FutureBuilder 做它的事情。

    【讨论】:

      【解决方案3】:

      你可以像这样使用FutureBuilder

      Future<bool> _value;
      
      @override
      void initState() {
        WidgetsBinding.instance!.addObserver(this);
        super.initState();
        _value = _getLastWorkoutId();
      }
      

      在你的build 方法中你有:

       FutureBuilder<bool>(
          future: _value,
          builder: (
            BuildContext context,
            AsyncSnapshot<bool> snapshot,
          ) {
            if (snapshot.hasData) {
              if (snapshot.data){
                 //update view 
               }else{
                 //update view
               }
            }
          }
      

      方法可以是这样的:

         _getLastWorkoutId() async {
              try {
                var snapshot = await usersRef
                    .doc(currentUser!.uid)
                    .collection('workouts')
                    .orderBy('workoutDate', descending: true)
                    .limit(1)
                    .snapshots()
                    .first; 
                for (var element in snapshot.docs) {
                  workoutId = element.id;
                  return true;
                }
              } catch (e) {
                print(e.toString());
              }
            }
      

      Here你可以找到更多关于FutureBuilder的信息。

      【讨论】:

      • 为什么是布尔值?另外,我在你写更新视图的地方返回什么?我只需要更新一个值。
      • 将数据类型更改为您的方法返回的任何内容。另外,在 build 方法中你应该更新 UI!
      猜你喜欢
      • 1970-01-01
      • 2021-03-24
      • 1970-01-01
      • 2021-01-07
      • 2013-08-09
      • 1970-01-01
      • 2020-12-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多