NoSuchMethodError: The method 'ancestorStateOfType' was called on null with await and async method

Louis Chovaneck picture Louis Chovaneck · May 29, 2019 · Viewed 11.9k times · Source

i would like to create a loader data, at the end the load of the data the screen will automaticly change the screen (with Navigator).

BUT i have some problem.

Unhandled Exception: NoSuchMethodError: The method 'ancestorStateOfType' was called on null.

At the end of the method "getDataOfUser()" the "print(a)" executed fine but when it try to change the screen it crash and i have this error :

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'),
    );

  }

}

Answer

Michael Yuwono picture Michael Yuwono · May 29, 2019

Your context was never assigned. You are calling Navigator using that context while it is still null. Try to assign it with the context from the page when it is built.

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