初始化 BLoC 时应该如何处理异步调用?
Posted
技术标签:
【中文标题】初始化 BLoC 时应该如何处理异步调用?【英文标题】:How should I handle asynchronous calls when initializing my BLoC? 【发布时间】:2019-12-13 07:27:07 【问题描述】:我正在使用 Provider
包向我的 Flutter 应用程序提供 BLoC 对象(手写,而不是使用 bloc
或 flutter_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 时应该如何处理异步调用?的主要内容,如果未能解决你的问题,请参考以下文章