flutter - 在 initState 中调用提供者上下文
问题描述
我想在 initState 方法中从数据库中获取一个值。因此,我尝试通过使用 Provider.of(context) 方法调用函数来访问该值。但是,我收到以下错误:
E/flutter ( 6424): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: Error: Could not find the correct Provider<RestaurantTimings> above this MyApp Widget
E/flutter ( 6424):
E/flutter ( 6424): This likely happens because you used a `BuildContext` that does not include the provider
E/flutter ( 6424): of your choice. There are a few common scenarios:
E/flutter ( 6424):
E/flutter ( 6424): - The provider you are trying to read is in a different route.
E/flutter ( 6424):
E/flutter ( 6424): Providers are "scoped". So if you insert of provider inside a route, then
E/flutter ( 6424): other routes will not be able to access that provider.
E/flutter ( 6424):
E/flutter ( 6424): - You used a `BuildContext` that is an ancestor of the provider you are trying to read.
E/flutter ( 6424):
E/flutter ( 6424): Make sure that MyApp is under your MultiProvider/Provider<RestaurantTimings>.
E/flutter ( 6424): This usually happen when you are creating a provider and trying to read it immediately.
E/flutter ( 6424):
E/flutter ( 6424): For example, instead of:
E/flutter ( 6424): For example, instead of:
E/flutter ( 6424):
E/flutter ( 6424): ```
E/flutter ( 6424): Widget build(BuildContext context) {
E/flutter ( 6424): return Provider<Example>(
E/flutter ( 6424): create: (_) => Example(),
E/flutter ( 6424): // Will throw a ProviderNotFoundError, because `context` is associated
E/flutter ( 6424): // to the widget that is the parent of `Provider<Example>`
E/flutter ( 6424): child: Text(context.watch<Example>()),
E/flutter ( 6424): ),
E/flutter ( 6424): }
E/flutter ( 6424): ```
E/flutter ( 6424):
E/flutter ( 6424): consider using `builder` like so:
E/flutter ( 6424):
E/flutter ( 6424): ```
E/flutter ( 6424): Widget build(BuildContext context) {
E/flutter ( 6424): return Provider<Example>(
E/flutter ( 6424): create: (_) => Example(),
E/flutter ( 6424): // we use `builder` to obtain a new `BuildContext` that has access to the provider
E/flutter ( 6424): builder: (context) {
E/flutter ( 6424): // No longer throws
E/flutter ( 6424): return Text(context.watch<Example>()),
E/flutter ( 6424): }
E/flutter ( 6424): ),
E/flutter ( 6424): }
这是我的代码:
Future<void> main() async {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
var _isLoading = false;
var isOpen = false;
ClosingOpeningHours _timing;
void initState(){
super.initState();
_getTimingOrClosing();
}
_getTimingOrClosing() async{
_timing = await Provider.of<RestaurantTimings>(context, listen: false)
.fetchTiming();
print('Start close in main ' + _timing.startClose);
}
Future<void> _initPackageInfo() async {
setState(() {
_isLoading = true;
});
print('Inside initPackageInfo');
final info = await PackageInfo.fromPlatform();
setState(() {
_packageInfo = info;
});
}
@override
Widget build(BuildContext context) {
return !(_isLoading)?MultiProvider(
providers: [
ChangeNotifierProvider(
create: (_) => Auth(),
),
ChangeNotifierProxyProvider<Auth, Products>(
create:null,
update:(ctx,auth, previousProducts) => Products(auth.token,
auth.userId)),
ChangeNotifierProvider(
create: (_) => Cart(),
),
ChangeNotifierProvider(
create: (_) => ColorChanger(),
),
ChangeNotifierProxyProvider<Auth,RestaurantTimings>(
create:null,
update:(ctx,auth, previousTimings) => RestaurantTimings(auth.token)),
],
//The consumer ensures that the material app gets built whenever Auth object changes
child: Consumer<Auth>(builder: (ctx, auth, _) =>
MaterialApp(
navigatorKey: navigatorKey,
title: 'MyApp',
theme: ThemeData(
textTheme: Theme.of(context).textTheme.apply(
bodyColor: Colors.black,
displayColor: Colors.black,
),
primaryColor: Colors.white,
accentColor: Color(0xFFF2AD18),
fontFamily: 'Muli',
),
home:
auth.isAuth && !isopen ? StoreTimings(): auth.isAuth && isopen?
CategoriesScreen()
: FutureBuilder(
future: auth.tryAutoLogin(),
builder: (ctx, authResultSnapshot) =>
authResultSnapshot.connectionState ==
ConnectionState.waiting
? Center(
child: Loading(),
)
: LoginPage(),
),
routes: {
ProductDetailScreen.routeName:(ctx) => ProductDetailScreen(),
}
),
)
):Center(child:Loading());
}
}
引发此错误的具体代码是:
_timing = await Provider.of<RestaurantTimings>(context, listen: false)
.fetchTiming();
如果您查看我的代码,您会看到我已经RestaurantTiming
在 multiprovider 中列出。我真的需要在主 UI 构建之前运行它。
解决方案
我不确定它是否有效,但你介意这样尝试吗
@override
void initState() {
super.initState();
SchedulerBinding.instance.addPostFrameCallback((_) async {
_getTimingOrClosing();
});
}
推荐阅读
- git - Visual Studio - Azure Dev:未能将分支推送到远程存储库
- automation - 如何将功能文件链接到 Python BDD 中的多个步骤定义文件
- pdf - 将 LaTex PDF 从矢量转换为光栅
- java - JAVA:输入地址值时如何使空格(“”)可读?
- node.js - 使用 socketio-file-upload 将文件保存到 mongoDb
- angular - 无法使用 Firebase 和 Angular 显示数据
- javascript - 如何在 aws dynamodb 上创建表
- html - 文本未垂直居中
- laravel - 将 laravel 添加到已经在 web 上使用 laravel 运行的现有项目
- python - Jupyter Notebook - 第二次无法获取用户输入 - EOFError:读取一行时出现EOF