初始化我的 BLoC 时应该如何处理异步调用?
How should I handle asynchronous calls when initializing my BLoC?
我正在使用 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()
在我们深入应用程序之前完成,以便依赖 settings/other 的代码加载正确的信息(对于例如,我希望在外出进行一些网络呼叫、初始化通知等之前加载设置。
据我了解,构造函数不能是异步的,所以我不能在构造函数上 await
。我试过给我的 BLoC 一个 init()
函数(或类似的东西)调用 _loadSettings()
and/or _loadOtherStuff()
,但我很难找到一个好地方把它。
我应该把这些电话放在哪里?还是我误会了async/await
?
您可以使用流来侦听完成。
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
},
我最后还使用了 Future.wait() 的一些帮助:
Future.wait([_loadSettings(), _loadOtherStuff()]).then((_) => _doMoreStuff());
这确保在我们继续之前完成前两个。
我正在使用 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()
在我们深入应用程序之前完成,以便依赖 settings/other 的代码加载正确的信息(对于例如,我希望在外出进行一些网络呼叫、初始化通知等之前加载设置。
据我了解,构造函数不能是异步的,所以我不能在构造函数上 await
。我试过给我的 BLoC 一个 init()
函数(或类似的东西)调用 _loadSettings()
and/or _loadOtherStuff()
,但我很难找到一个好地方把它。
我应该把这些电话放在哪里?还是我误会了async/await
?
您可以使用流来侦听完成。
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
},
我最后还使用了 Future.wait() 的一些帮助:
Future.wait([_loadSettings(), _loadOtherStuff()]).then((_) => _doMoreStuff());
这确保在我们继续之前完成前两个。