NoSuchMethodError: The method 'ancestorStateOfType' was called on null with await and async method
NoSuchMethodError: The method 'ancestorStateOfType' was called on null with await and async method
我想创建一个loader数据,加载完数据屏幕会自动换屏(用Navigator)。
但是我有一些问题。
Unhandled Exception: NoSuchMethodError: The method 'ancestorStateOfType' was called on null.
在方法 "getDataOfUser()" 结束时,"print(a)" 执行得很好,但是当它尝试更改屏幕时它崩溃了,我有这个错误:
E/flutter (32148): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: NoSuchMethodError: The method 'ancestorStateOfType' was called on null.
E/flutter (32148): Receiver: null
E/flutter (32148): Tried calling: ancestorStateOfType(Instance of 'TypeMatcher<NavigatorState>')
E/flutter (32148): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:50:5)
E/flutter (32148): #1 Navigator.of (package:flutter/src/widgets/navigator.dart:1446:19)
E/flutter (32148): #2 LoginScreenPresenter.initState.<anonymous closure> (package:test_app/login_presenter.dart:35:17)
class loginPresenter extends StatefulWidget {
Vendeur v;
loginPresenter({Key key, this.v}) : super(key: key);
@override
LoginScreenPresenter createState() => new LoginScreenPresenter();
}
class LoginScreenPresenter extends State<loginPresenter> {
RestDatasource api = new RestDatasource();
BuildContext context;
bool finish = false;
@override
void initState() {
getDataOfUser(widget.v).then((a) {
print(a)
Navigator.of(context).pushReplacement(new MaterialPageRoute(
builder: (BuildContext context) => HomePage(
v: widget.v,
)));
});
super.initState();
}
Future<bool> getDataOfUser(Vendeur user) async {
await api.getRegionsFromUser(user.idV).then((list) async {
if (list != null) {
for (var i = 0; i < list.length; ++i) {
await DBProvider.db.newRegion(list[i], 1);
}
}
});
await api.getClientsFromUser(user.idV).then((list) async {
if (list != null) {
for (var i = 0; i < list.length; ++i) {
await DBProvider.db.newClient(list[i], 1);
}
}
});
await api.getInterlocuteursFromUser(user.idV).then((list) async {
if (list != null) {
for (var i = 0; i < list.length; ++i) {
await DBProvider.db.newInterlocuteurs(list[i], 1);
}
}
});
await api.getVisitesFromUser(user.idV).then((list) async {
if (list != null) {
for (var i = 0; i < list.length; ++i) {
await DBProvider.db.newVisite(list[i], 1);
}
}
});
await api.getAvoirsFromUser(user.idV).then((list) async {
if (list != null) {
for (var i = 0; i < list.length; ++i) {
if (list[i].deleted == 0) {
await DBProvider.db.newAvoir(list[i], 1);
}
}
}
});
await api.getRapportsFromUser(user.idV).then((list) async {
if (list != null) {
for (var i = 0; i < list.length; ++i) {
await DBProvider.db.newRapport(list[i], user);
}
}
});
return true;
}
@override
Widget build(context) {
return RaisedButton(
onPressed: () {
Navigator.push(
context,
SlideRightRoute(
widget: HomePage(
v: widget.v,
)));
},
child: Text('go'),
);
}
}
您的 context
从未分配过。您正在使用该上下文调用导航器,而它仍然为空。尝试在构建时为其分配页面中的上下文。
@override
Widget build(context) {
setState(() => this.context = context);
...
}
我遇到了这个问题,我检查了 mounted
,现在一切正常。
{...
if(!mounted) return;
Navigator.of(context).pop();
...}
如果您在执行操作时尝试实现加载对话框,请注意,如果您的对话框没有时间实际构建自身,它将抛出此错误。
下面的例子很可能会失败,因为 showLoadingDialog
和对应的 pop
之间没有延迟,所以 context
没有时间存在于 showLoadingDialog
还:
///DON'T DO THIS
final GlobalKey<State> _loadingKey = GlobalKey<State>();
ListTile(
leading: Text("Sign Out"),
onTap: () async {
showLoadingDialog(context, _loadingKey);
Navigator.of(_loadingKey.currentContext, rootNavigator: true)
.pop();
},
),
但是,允许 showLoadingDialog
构建的延迟应该允许 pop
工作而不会显示错误:
/// This works without error
final GlobalKey<State> _loadingKey = GlobalKey<State>();
ListTile(
leading: Text("Sign Out"),
onTap: () async {
showLoadingDialog(context, _loadingKey);
await Future.delayed(Duration(seconds: 2));
Navigator.of(_loadingKey.currentContext, rootNavigator: true)
.pop();
},
),
我并不是建议您在代码中添加 await Future.delayed...
语句以使对话框正常工作,但我最初无法弄清楚为什么某些 showLoadingDialog
可以正常工作,并且一个不是 - 所以希望这可以引导某人更快地解决问题。
我正在使用全局状态变量
final GlobalKey<State> _keyLoader = new GlobalKey<State>();
我试图使用下面的代码行弹出上下文
Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop();
因为我的代码有很多嵌套循环,所以这段代码给了我错误。我改为使用下面的代码来修复此错误消息
Navigator.of(context, rootNavigator: true).pop();
有时会发现,在嵌套循环中,使用全局状态变量时上下文设置不正确,可能会导致此错误消息。
我想创建一个loader数据,加载完数据屏幕会自动换屏(用Navigator)。
但是我有一些问题。
Unhandled Exception: NoSuchMethodError: The method 'ancestorStateOfType' was called on null.
在方法 "getDataOfUser()" 结束时,"print(a)" 执行得很好,但是当它尝试更改屏幕时它崩溃了,我有这个错误:
E/flutter (32148): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: NoSuchMethodError: The method 'ancestorStateOfType' was called on null.
E/flutter (32148): Receiver: null
E/flutter (32148): Tried calling: ancestorStateOfType(Instance of 'TypeMatcher<NavigatorState>')
E/flutter (32148): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:50:5)
E/flutter (32148): #1 Navigator.of (package:flutter/src/widgets/navigator.dart:1446:19)
E/flutter (32148): #2 LoginScreenPresenter.initState.<anonymous closure> (package:test_app/login_presenter.dart:35:17)
class loginPresenter extends StatefulWidget {
Vendeur v;
loginPresenter({Key key, this.v}) : super(key: key);
@override
LoginScreenPresenter createState() => new LoginScreenPresenter();
}
class LoginScreenPresenter extends State<loginPresenter> {
RestDatasource api = new RestDatasource();
BuildContext context;
bool finish = false;
@override
void initState() {
getDataOfUser(widget.v).then((a) {
print(a)
Navigator.of(context).pushReplacement(new MaterialPageRoute(
builder: (BuildContext context) => HomePage(
v: widget.v,
)));
});
super.initState();
}
Future<bool> getDataOfUser(Vendeur user) async {
await api.getRegionsFromUser(user.idV).then((list) async {
if (list != null) {
for (var i = 0; i < list.length; ++i) {
await DBProvider.db.newRegion(list[i], 1);
}
}
});
await api.getClientsFromUser(user.idV).then((list) async {
if (list != null) {
for (var i = 0; i < list.length; ++i) {
await DBProvider.db.newClient(list[i], 1);
}
}
});
await api.getInterlocuteursFromUser(user.idV).then((list) async {
if (list != null) {
for (var i = 0; i < list.length; ++i) {
await DBProvider.db.newInterlocuteurs(list[i], 1);
}
}
});
await api.getVisitesFromUser(user.idV).then((list) async {
if (list != null) {
for (var i = 0; i < list.length; ++i) {
await DBProvider.db.newVisite(list[i], 1);
}
}
});
await api.getAvoirsFromUser(user.idV).then((list) async {
if (list != null) {
for (var i = 0; i < list.length; ++i) {
if (list[i].deleted == 0) {
await DBProvider.db.newAvoir(list[i], 1);
}
}
}
});
await api.getRapportsFromUser(user.idV).then((list) async {
if (list != null) {
for (var i = 0; i < list.length; ++i) {
await DBProvider.db.newRapport(list[i], user);
}
}
});
return true;
}
@override
Widget build(context) {
return RaisedButton(
onPressed: () {
Navigator.push(
context,
SlideRightRoute(
widget: HomePage(
v: widget.v,
)));
},
child: Text('go'),
);
}
}
您的 context
从未分配过。您正在使用该上下文调用导航器,而它仍然为空。尝试在构建时为其分配页面中的上下文。
@override
Widget build(context) {
setState(() => this.context = context);
...
}
我遇到了这个问题,我检查了 mounted
,现在一切正常。
{...
if(!mounted) return;
Navigator.of(context).pop();
...}
如果您在执行操作时尝试实现加载对话框,请注意,如果您的对话框没有时间实际构建自身,它将抛出此错误。
下面的例子很可能会失败,因为 showLoadingDialog
和对应的 pop
之间没有延迟,所以 context
没有时间存在于 showLoadingDialog
还:
///DON'T DO THIS
final GlobalKey<State> _loadingKey = GlobalKey<State>();
ListTile(
leading: Text("Sign Out"),
onTap: () async {
showLoadingDialog(context, _loadingKey);
Navigator.of(_loadingKey.currentContext, rootNavigator: true)
.pop();
},
),
但是,允许 showLoadingDialog
构建的延迟应该允许 pop
工作而不会显示错误:
/// This works without error
final GlobalKey<State> _loadingKey = GlobalKey<State>();
ListTile(
leading: Text("Sign Out"),
onTap: () async {
showLoadingDialog(context, _loadingKey);
await Future.delayed(Duration(seconds: 2));
Navigator.of(_loadingKey.currentContext, rootNavigator: true)
.pop();
},
),
我并不是建议您在代码中添加 await Future.delayed...
语句以使对话框正常工作,但我最初无法弄清楚为什么某些 showLoadingDialog
可以正常工作,并且一个不是 - 所以希望这可以引导某人更快地解决问题。
我正在使用全局状态变量
final GlobalKey<State> _keyLoader = new GlobalKey<State>();
我试图使用下面的代码行弹出上下文
Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop();
因为我的代码有很多嵌套循环,所以这段代码给了我错误。我改为使用下面的代码来修复此错误消息
Navigator.of(context, rootNavigator: true).pop();
有时会发现,在嵌套循环中,使用全局状态变量时上下文设置不正确,可能会导致此错误消息。