whenComplete() 方法没有按预期工作 - Flutter Async

Posted

技术标签:

【中文标题】whenComplete() 方法没有按预期工作 - Flutter Async【英文标题】:whenComplete() method not working as expected - Flutter Async 【发布时间】:2019-10-29 05:50:53 【问题描述】:

在我的 Flutter 应用程序中,我尝试使用 whenComplete() 方法在异步函数完成后运行一些代码。问题是我的 whenComplete() 方法中的代码甚至在异步函数完成之前就被执行了。

我也尝试过使用 then() 方法,这也产生了相同的结果。

这是我调用异步函数的初始化函数:

@override
  void initState() 
    super.initState();

    FirebaseAuth.instance.currentUser().then((user) 
      setState(() 
        mUid = user.uid;

        getUserName();
        getUserHomes().whenComplete(() 
          print(mUserHomes);
          setState(() 
            dropdownVal = mUserHomes[0];
          );
        );
      );
    ).catchError((e) 
      print(e);
    );
  

这是异步函数的函数体:

Future getUserHomes() async 
    CollectionReference ref = Firestore.instance
        .collection('users')
        .document(mUid)
        .collection('accessibleHomes');
    QuerySnapshot eventsQuery = await ref.getDocuments();

    eventsQuery.documents.forEach((document) 
      DocumentReference homeReference = document["homeReference"];

      getHomeDevices("home", homeReference).whenComplete(() 
        setState(() );
      );

      homeReference.get().then((DocumentSnapshot ds) 
        mUserHomes.add(ds["alias"].toString());
      );
    );
  

运行应用时的控制台输出为:

Performing hot restart...
Syncing files to device ASUS Z01RD...
Restarted application in 2,521ms.
I/flutter ( 5718): []
E/flutter ( 5718): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: RangeError (index): Invalid value: Valid value range is empty: 0
E/flutter ( 5718): #0      List.[] (dart:core-patch/growable_array.dart:145:60)
E/flutter ( 5718): #1      _TabOneState.initState.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:smart_switch/home/tabs/tab_one/tab_one_content.dart:52:37)
E/flutter ( 5718): #2      State.setState (package:flutter/src/widgets/framework.dart:1117:30)
E/flutter ( 5718): #3      _TabOneState.initState.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:smart_switch/home/tabs/tab_one/tab_one_content.dart:51:11)
E/flutter ( 5718): #4      _rootRun (dart:async/zone.dart:1120:38)
E/flutter ( 5718): #5      _CustomZone.run (dart:async/zone.dart:1021:19)
E/flutter ( 5718): #6      _FutureListener.handleWhenComplete (dart:async/future_impl.dart:150:18)
E/flutter ( 5718): #7      Future._propagateToListeners.handleWhenCompleteCallback (dart:async/future_impl.dart:609:39)
E/flutter ( 5718): #8      Future._propagateToListeners (dart:async/future_impl.dart:665:37)
E/flutter ( 5718): #9      Future._complete (dart:async/future_impl.dart:473:7)
E/flutter ( 5718): #10     _SyncCompleter.complete (dart:async/future_impl.dart:51:12)
E/flutter ( 5718): #11     _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:28:18)
E/flutter ( 5718): #12     _completeOnAsyncReturn (dart:async-patch/async_patch.dart:294:13)
E/flutter ( 5718): #13     _TabOneState.getUserHomes (package:smart_switch/home/tabs/tab_one/tab_one_content.dart)
E/flutter ( 5718): #14     _asyncThenWrapperHelper.<anonymous closure> (dart:async-patch/async_patch.dart:77:64)
E/flutter ( 5718): #15     _rootRunUnary (dart:async/zone.dart:1132:38)
E/flutter ( 5718): #16     _CustomZone.runUnary (dart:async/zone.dart:1029:19)
E/flutter ( 5718): #17     _FutureListener.handleValue (dart:async/future_impl.dart:126:18)
E/flutter ( 5718): #18     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:639:45)
E/flutter ( 5718): #19     Future._propagateToListeners (dart:async/future_impl.dart:668:32)
E/flutter ( 5718): #20     Future._complete (dart:async/future_impl.dart:473:7)
E/flutter ( 5718): #21     _SyncCompleter.complete (dart:async/future_impl.dart:51:12)
E/flutter ( 5718): #22     _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:28:18)
E/flutter ( 5718): #23     _completeOnAsyncReturn (dart:async-patch/async_patch.dart:294:13)
E/flutter ( 5718): #24     Query.getDocuments (package:cloud_firestore/src/query.dart)
E/flutter ( 5718): #25     _asyncThenWrapperHelper.<anonymous closure> (dart:async-patch/async_patch.dart:77:64)
E/flutter ( 5718): #26     _rootRunUnary (dart:async/zone.dart:1132:38)
E/flutter ( 5718): #27     _CustomZone.runUnary (dart:async/zone.dart:1029:19)
E/flutter ( 5718): #28     _FutureListener.handleValue (dart:async/future_impl.dart:126:18)
E/flutter ( 5718): #29     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:639:45)
E/flutter ( 5718): #30     Future._propagateToListeners (dart:async/future_impl.dart:668:32)
E/flutter ( 5718): #31     Future._complete (dart:async/future_impl.dart:473:7)
E/flutter ( 5718): #32     _SyncCompleter.complete (dart:async/future_impl.dart:51:12)
E/flutter ( 5718): #33     _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:28:18)
E/flutter ( 5718): #34     _completeOnAsyncReturn (dart:async-patch/async_patch.dart:294:13)
E/flutter ( 5718): #35     MethodChannel.invokeMapMethod (package:flutter/src/services/platform_channel.dart)
E/flutter ( 5718): #36     _asyncThenWrapperHelper.<anonymous closure> (dart:async-patch/async_patch.dart:77:64)
E/flutter ( 5718): #37     _rootRunUnary (dart:async/zone.dart:1132:38)
E/flutter ( 5718): #38     _CustomZone.runUnary (dart:async/zone.dart:1029:19)
E/flutter ( 5718): #39     _FutureListener.handleValue (dart:async/future_impl.dart:126:18)
E/flutter ( 5718): #40     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:639:45)
E/flutter ( 5718): #41     Future._propagateToListeners (dart:async/future_impl.dart:668:32)
E/flutter ( 5718): #42     Future._complete (dart:async/future_impl.dart:473:7)
E/flutter ( 5718): #43     _SyncCompleter.complete (dart:async/future_impl.dart:51:12)
E/flutter ( 5718): #44     _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:28:18)
E/flutter ( 5718): #45     _completeOnAsyncReturn (dart:async-patch/async_patch.dart:294:13)
E/flutter ( 5718): #46     MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart)
E/flutter ( 5718): #47     _asyncThenWrapperHelper.<anonymous closure> (dart:async-patch/async_patch.dart:77:64)
E/flutter ( 5718): #48     _rootRunUnary (dart:async/zone.dart:1132:38)
E/flutter ( 5718): #49     _CustomZone.runUnary (dart:async/zone.dart:1029:19)
E/flutter ( 5718): #50     _FutureListener.handleValue (dart:async/future_impl.dart:126


所以在我调用异步函数 getUserHomes 的 init() 函数中,我试图将 dropdownVal 变量设置为从 Firestore DB 获取的列表 mUserHomes 的第一个值。该列表在控制台中打印为 [] 表示为空,但如果我在稍后阶段打印该列表,它将与值一起打印。

【问题讨论】:

【参考方案1】:

您的getUserHomes 函数在它不等待的foreach 回调中执行大量异步工作,因此getUserHomes 几乎在ref.getDocuments 完成后立即完成其返回的Future

如果您想等待getUserHomes 中的所有工作完成,您可以执行以下操作:

Future<void> getUserHomes() async 
  CollectionReference ref = Firestore.instance
      .collection('users')
      .document(mUid)
      .collection('accessibleHomes');
  QuerySnapshot eventsQuery = await ref.getDocuments();

  final waitList = <Future<void>>[];

  for (var document in eventsQuery.documents) 
    DocumentReference homeReference = document["homeReference"];

    waitList.add(getHomeDevices("home", homeReference));
    waitList.add(
      homeReference.get().then((DocumentSnapshot ds) 
        mUserHomes.add(ds["alias"].toString());
      );
    );
  

  await Future.wait(waitList);

【讨论】:

【参考方案2】:

我遇到了同样的问题,并意识到如果你使用 for 循环而不是使用 foreach 方法,事情会按预期工作

【讨论】:

以上是关于whenComplete() 方法没有按预期工作 - Flutter Async的主要内容,如果未能解决你的问题,请参考以下文章

手表没有按预期工作

resignFirstResponder 没有按预期工作

Jquery .load 没有按预期工作[重复]

CAAnimation 在 CALayer 上没有按预期工作

重新编码数据框变量时,分配没有按预期工作?

laravel 会话刷新和忘记方法无法按预期工作