【问题标题】:How should I handle asynchronous calls when initializing my BLoC?初始化 BLoC 时应该如何处理异步调用?
【发布时间】:2019-12-13 07:27:07
【问题描述】:

我正在使用 Provider 包向我的 Flutter 应用程序提供 BLoC 对象(手写,而不是使用 blocflutter_bloc 包)。我需要进行一些异步调用才能正确初始化 BLoC(例如,来自SharedPreferences 的设置和其他保存的信息)。到目前为止,我已经将这些 async 调用编写到几个单独的函数中,这些函数在我的 BLoC 的构造函数中调用:

class MyBloc {

  MySettings _settings;
  List<MyOtherStuff> _otherStuff;

  MyBloc() {
      _loadSettings();
      _loadOtherStuff();
  }

  Future<void> _loadSettings() async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();

    // loads settings into _settings...
  }

  Future<void> _loadOtherStuff() async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();

    // loads other stuff into _otherStuff...
  }
}

我想保证 _loadSettings()_loadOtherStuff() 在我们深入应用程序之前完成,以便依赖于设置/其他内容的代码加载正确的信息(例如,我希望加载设置在我出去打一些网络电话、初始化通知等之前)。

据我了解,构造函数不能是异步的,所以我不能在构造函数上await。我尝试为我的 BLoC 提供一个调用 _loadSettings() 和/或 _loadOtherStuff()init() 函数(或类似函数),但我很难找到一个放置它的好地方。

我应该把这些电话放在哪里?还是我误会async/await

【问题讨论】:

    标签: asynchronous flutter bloc flutter-provider


    【解决方案1】:

    您可以使用流来监听完成。

    class MyBloc {
    
      MySettings _settings;
      List<MyOtherStuff> _otherStuff;
    
      final _completer = StreamController<Void>.broadcast();
    
      Stream<void> get completer => _completer.stream;
    
    
      MyBloc() {
        allInit();
    
      }
    
      allInit()async{
        await _loadSettings();
        await _loadOtherStuff();
        _completer.sink.add(null);
      }
    
      Future<void> _loadSettings() async {
        final SharedPreferences prefs = await SharedPreferences.getInstance();
    
    
        // loads settings into _settings...
        return;
      }
    
      Future<void> _loadOtherStuff() async {
        final SharedPreferences prefs = await SharedPreferences.getInstance();
    
        // loads other stuff into _otherStuff...
        return;
      }
    
    
    }
    

    然后你使用 streamBuilder

      return StreamBuilder(
        stream: myBloc.completer,
        builder: (context, AsyncSnapshot snapshot) {
          if (!snapshot.hasData) return Text('loading...');
        //stuff to run after init
      }, 
    

    【讨论】:

      【解决方案2】:

      我最终还使用了来自 Future.wait() 的一些帮助:

      Future.wait([_loadSettings(), _loadOtherStuff()]).then((_) => _doMoreStuff());
      

      这可以确保在我们继续之前完成前两个。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-12-06
        • 2019-08-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-21
        • 1970-01-01
        相关资源
        最近更新 更多