我遇到了providerNotFoundException,我怀疑下面的代码中存在上下文不匹配的情况,但是我很难看到它。据我了解,当在同一构建方法中执行.of方法时,BuilderContext会出现问题,但在这种情况下我看不到这种情况。如下面的代码所示,某些Provider.of方法可以正常工作,但是一旦调用SchedulingPage,Provider.of方法就不再起作用。
这是什么问题?
编辑:我更新为使用下面的完整代码: 这是完整的错误:ProviderNotFoundException(错误:在此LoginForm小部件上方找不到正确的提供程序
void main() {
runApp(
Home(),
);
}
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
// ChangeNotifierProvider(create: (context) => CalendarData()),
ChangeNotifierProvider(create: (context) => LayoutData()),
],
child: MyApp(),
);
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: SafeArea(
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
print("constraints: $constraints");
Size mediaSize = MediaQuery.of(context).size;
double safeAreaSize = mediaSize.height - constraints.maxHeight;
Provider.of<LayoutData>(context).safeAreaDiff = safeAreaSize;
Provider.of<LayoutData>(context).safeArea = constraints;
Provider.of<LayoutData>(context).mediaArea = mediaSize;
var test = Provider.of<LayoutData>(context).mediaArea.width;
print(test); // this works
return Scaffold(body: LoginScreen());
}),
),
);
}
}
class LoginScreen extends StatelessWidget {
const LoginScreen({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
double test = Provider.of<LayoutData>(context).mediaArea.width;
print("test: $test"); // this works
return LoginForm();
}
}
class LoginForm extends StatefulWidget {
LoginForm({Key key}) : super(key: key);
@override
_LoginFormState createState() => _LoginFormState();
}
class _LoginFormState extends State<LoginForm> {
@override
Widget build(BuildContext context) {
double width = Provider.of<LayoutData>(context).mediaArea.width; // The code fails here
print('width: $width');
return Text("this is where it fails ^^^^^^^^");
}
}
class LayoutData with ChangeNotifier {
double safeAreaDiff = 0.0;
BoxConstraints safeArea;
Size mediaArea;
LayoutData() {
initializeApp();
}
void initializeApp() {
print("layout initialized");
}
}
答案 0 :(得分:1)
您不能在您创建的同一类中访问提供程序。那必须是父窗口小部件。
void main() {
runApp(Home());
}
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => CalendarData()),
ChangeNotifierProvider(create: (context) => LayoutData()),
],
child: MyApp(),
);
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: SafeArea(
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
print("constraints: $constraints");
Size mediaSize = MediaQuery.of(context).size;
double safeAreaSize =
mediaSize.height - constraints.maxHeight; // works
Provider.of<LayoutData>(context).safeAreaDiff =
safeAreaSize; // works
Provider.of<LayoutData>(context).safeArea = constraints; // works
Provider.of<LayoutData>(context).mediaArea = mediaSize; // works
Provider.of<CalendarData>(context).working = "beer"; // works
print(Provider.of<CalendarData>(context).working); // works
return Scaffold(body: SchedulingPage());
}),
),
);
}
}
输出:
Performing hot restart...
Restarted application in 1,181ms.
I/flutter (25187): constraints: BoxConstraints(w=411.4, h=659.4)
I/flutter (25187): layout initialized
I/flutter (25187): 411.42857142857144
I/flutter (25187): test: 411.42857142857144
I/flutter (25187): width: 411.42857142857144
答案 1 :(得分:0)
您是否尝试过将MultiProvider()放在MaterialApp()上方?
答案 2 :(得分:0)
我发布此邮件的偶然机会是有人遇到与我相同的问题。事实证明,所选解决方案无法解决问题。所编写的代码应该有效。但是,在这种情况下,很难找到解决方案。事实证明,导入本身是不正确的。提供商数据类有两次导入,如下所示:
import 'package:myProject/providers/CalendarData.dart';
和
import 'package:gcfdlayout2/Providers/CalendarData.dart';
我相信这种歧义使IDE迷惑了,尽管它在构建时没有给我任何错误,但在运行时确实给了我错误,但是“找不到提供程序”让我以为它找不到。树中的提供者,而不是代码本身。
我最终发现的方法是使用其他运行代码的方法。最初,我只是使用Visual Studio Code,但从未出现任何错误提示它是导入问题。我改用Android Studio,它通知我CalendarData类有两个导入。