初始化 BLoC 时应该如何处理异步调用?

Posted

技术标签:

【中文标题】初始化 BLoC 时应该如何处理异步调用?【英文标题】:How should I handle asynchronous calls when initializing my 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

【问题讨论】:

【参考方案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());

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

【讨论】:

以上是关于初始化 BLoC 时应该如何处理异步调用?的主要内容,如果未能解决你的问题,请参考以下文章

如何处理异步 axios api 调用

nodejs 异步应该如何处理

当循环中调用了异步函数时,Node.JS 将如何处理循环控制?

如何处理异步 sendMessage 调用?

应用程序如何处理异步响应 - 通过回调

如何处理 Alamofire 的异步特性 [重复]