我想在启动时从数据库获取状态。我在第一个窗口小部件上将provider与ChangeNotivierProvider一起使用。包含代码以供澄清。
这是我的主要方法,它具有提供我计划在应用程序中使用的状态的小部件:
void main() => runApp(
ChangeNotifierProvider(
child: MyApp(),
builder: (context) => StateDao.get(),
),
}
我的DAO只是从数据库返回状态(我使用sembast,但也可以很容易地是sqflite或Firebase)
Future<State> get() async {
// Database logic
}
状态只是扩展ChangeNotifier的对象
class State extends ChangeNotifier {
// Getters, setters, changeNotifiers etc.
}
这将不起作用,因为我无法在 ChangeNotifierProvider 的生成器方法中调用 async 方法。应该如何,何时何地进行初始化?据我了解,异步调用不应在任何构建方法中进行。我尝试覆盖了提供上下文访问的didChangeDependencies,但无法克服构建器方法限制中的异步调用。
答案 0 :(得分:1)
您可以在 initState 中初始化值。例如,您可以存储 Future 对象,并在解析值后使用 FutureBuilder 来构建窗口小部件:
Future<State> futureState;
@override
void initState() {
// Calling async method and storing Future object
futureState = StateDao.get();
super.initState();
}
@override
Widget build(BuildContext context) {
return FutureBuilder<State>(
future: futureState,
builder: (context, snapshot) {
// No data yet, showing loader
if (!snapshot.hasData) {
return CircularProgressIndicator();
}
return ChangeNotifierProvider(
child: MyApp(),
builder: (context) => snapshot.data,
);
},
);
}
另一种类似的方法是使用StreamController和StreamBuilder:
final StreamController<State> stateStream = StreamController<State>();
@override
void initState() {
// Calling async method and setting callback to add data to the stream
StateDao.get().then((v) => stateStream.add(v));
super.initState();
}
@override
void dispose() {
// Closing the sink
stateStream.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
return StreamBuilder<State>(
stream: stateStream.stream,
builder: (context, snapshot) {
// No data yet, showing loader
if (!snapshot.hasData) {
return CircularProgressIndicator();
}
return ChangeNotifierProvider(
child: MyApp(),
builder: (context) => snapshot.data,
);
},
);
}
如果您需要更复杂的体系结构,则可能需要看看BLoC,它是Flutter社区中非常流行的体系结构。