Подождите, пока Navigator.pop игнорирует Navigator.pushReplacement - PullRequest
1 голос
/ 10 июля 2020

У меня следующая настройка:

class FirstScreen {
  // ...
  Future<void> doSomething() async {
    final bool isCool = await Navigator.of(context).pushNamed('/second-screen');
    print(isCool ? 'Cool.' : 'Not cool.');
  }
  // ...
}

class SecondScreen {
  // ...
  Future<void> replace() async {
    await Navigator.of(context).pushReplacementNamed('/third-screen');
  }
  // ...
}

class ThirdScreen {
  // ...
  Future<void> goBack() async {
    await Navigator.of(context).pop(true);
  }
  // ...
}

Однако это приведет к ошибке sh, поскольку pushReplacement обрабатывает await, и мое приложение не будет ждать, пока pop не будет

Как я могу дождаться возврата значения pop?

ОБНОВЛЕНИЕ:

Проблема здесь немного сложнее, чем я сказал.

@ Алок предложил не pop маршрут, а sh его после последовательности, однако это очень тривиальная версия моего кода.

Сейчас у меня HomeScreen с вложенным Navigator, который открывает список вопросов. Затем, используя Navigator.of(context, rootNavigator: true), я перехожу к examLoadingScreen, et c. (Вы можете прочитать об этом в комментариях)

Если я сделаю sh HomeScreen по завершении экзамена, я потеряю всю навигацию, выполненную в упомянутом вложенном Navigator.

Мне серьезно нужно pop в этом сценарии. У меня есть несколько обходных путей, таких как цепочка pop, но это не кажется очень производительным или удобным.

1 Ответ

1 голос
/ 10 июля 2020

См. Зесвен, что касается этой документации по pushReplacementNamed . В нем указано, что =>

Заменить текущий маршрут навигатора, который наиболее плотно охватывает данный контекст, нажав маршрут с именами routeName и , а затем удалив предыдущий маршрут, когда новый маршрут завершена анимация в.

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

Теперь, что вы пытаетесь сделать достижение есть, или как Navigator.pop () работает извлечение значения, обязательно наличие PrevoiusPage там, когда вы переходите с одной страницы на другую

//What you're doing with pushReplacementNamed
1 -> SeconPage => ThidPage
2 -> SecondPage [Removed] 
3 -> ThirdPage is trying to come to the previous page, that is SecondPage to return it's value, but SecondPage has been removed HENCE CRASHES!!

//What is needs to be done to use something like push() or pushNamed(), which used named route
1 -> SecondPage => ThirdPage
2 -> SecondPage is there in the stack
3 -> ThirdPage => SecondPage [Returns Value]

ПОМНИТЕ pop() всегда нужен непосредственный приоритет, чтобы принять его значение, а не любую страницу. Итак, если вы удалите SecondPage, он всегда будет cra sh.

Теперь, если вы хотите go на страницу, MainPage или, в данном случае, FirstPage. Используйте pushAndRemoveUntil . Он в основном удаляет все маршруты в стеке и go на страницу

РЕШЕНИЕ: Передайте результат в MainPage через ResultPage. Сделайте так, чтобы MainPage также принимал оценку результата

class ThirdScreen(){
  // ...
  Future<void> goBack() async {
    await Navigator.pushAndRemoveUntil(context, 
        MaterialPageRoute( builder: (context) => FirstPage(result: result),
        (_) => false
    );
  }
}

И проделайте свою операцию в своем FirstPage соответственно, если у вас есть result != 0 || result != null, и покажите его пользователю. Дайте мне знать, если это сработает для вас.

ОБНОВЛЕННЫЙ ОТВЕТ С НАИЛУЧШИМ ВОЗМОЖНЫМ РЕШЕНИЕМ

Я только что добавил этот ответ, потому что мне кажется, что приведенное выше быть полезным и в будущем.

Сейчас моя идея - базовая c, и она работоспособна в соответствии с тривиальной информацией, доступной мне. Теоретически, к значению pop() может получить доступ только предшественник, immediate one.

РЕШЕНИЕ

1. First Page -> Second Page
2. Second Page -> Third Page
3. Third Page -> Second Page with value

// Now following 3. step
1. Value check, if the value is true, pop immediately
2. Return the value to the first page
3. Print the value in the first page

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

class FirstScreen {
  
  Future<void> doSomething() async {
    // We get the value from second page, which is technically passing 
    // the third page's value, and doesn't appear to us in UI
    // So serving the purpose
    final bool isCool = await Navigator.pushNamed(context, '/second-screen');
    print(isCool ? 'Cool.' : 'Not cool.');
  }
}

class SecondScreen {

  Future<void> replace() async {
    // No need of pushReplacementNamed, since we're are popping 
    // based upon our values, so it won't appear eventually
    // and pass the value as well for the First Page
    final bool value = await Navigator.pushNamed(context, '/third-screen');

    // Now we check, whether what value we got from third page,
    // If that is true, then immediately pop and return the value for first page
    if(value == true){
        Navigator.pop(context, value);
    }
  }
}

class ThirdScreen {
  // async not required for performing pop()
  // void is fine
  void goBack() {
    Navigator.pop(context, true);
  }
}

Просто проверьте это, дайте мне знать. Этот лог c определенно поможет вам достичь цели, , и он безопасен и без ошибок :) Удачного обучения :)

...