NoSuchMethodError:使用等待和异步方法在null上调用了方法'ancestorStateOfType'

时间:2019-05-29 14:03:00

标签: android flutter dart navigator

我想创建一个加载器数据,最后,屏幕加载的数据将自动更改屏幕(使用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'),
    );

  }

}

4 个答案:

答案 0 :(得分:3)

我遇到了这个问题,我检查了mounted,现在一切正常。

{...
  if(!mounted) return;
  Navigator.of(context).pop();
...}

答案 1 :(得分:0)

您的context从未分配。您正在使用仍为空的上下文调用Navigator。构建时,尝试从页面中为其分配上下文。

@override
Widget build(context) {
  setState(() => this.context = context);
  ...
}

答案 2 :(得分:0)

如果您在执行操作时尝试实现加载对话框,请注意,如果对话框没有时间进行实际构建,则会引发此错误。

以下示例可能会失败,因为showLoadingDialog及其对应的pop之间没有延迟,因此context没有时间存在于{{1 }}:

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...可以正常工作,而有些却无法正常工作没错-希望这可以指导某人更快地解决问题。

答案 3 :(得分:0)

我正在使用全局状态变量
final GlobalKey<State> _keyLoader = new GlobalKey<State>();

我试图使用下面的代码行弹出上下文 Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop();

由于我的代码有许多嵌套循环,因此该代码给了我错误。我改用下面的代码来修复此错误消息

Navigator.of(context, rootNavigator: true).pop();

有时会发现在嵌套循环中,使用全局状态变量时上下文设置不正确,并且可能导致出现此错误消息。