NoSuchMethodError: метод ancestorStateOfType был вызван с нулевым значением с помощью метода ожидания и асинхронного

я хотел бы создать загрузчик данных, в конце загрузки данных экран автоматически изменит экран (с навигатором).

НО у меня есть проблема.

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

  }

}
8
0
14 541
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Ваш context никогда не назначался. Вы вызываете Navigator, используя этот контекст, пока он все еще равен нулю. Попробуйте присвоить ему контекст со страницы при его построении.

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

Привет, у меня похожий случай, но у меня другая структура, пожалуйста, помогите. Стараюсь не задавать новый вопрос. Вот мой код: codepen.io/easy-pbnl/pen/BaNaQpX Строка 37, где проблема, пожалуйста, как мне установить контекст в этой точке?

Israel Obanijesu 06.02.2020 05:06

'context', конечная переменная, может быть установлена ​​только один раз. Попробуйте сделать "контекст" не окончательным.

Yudhishthir Singh 19.05.2020 08:27

У меня возникла эта проблема, и я проверил 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();

Время от времени наблюдается, что во вложенном цикле контекст неправильно установлен при использовании глобальной переменной состояния и может привести к этому сообщению об ошибке.

Другие вопросы по теме