等待Navigator.pop忽略Navigator.pushReplacement

时间:2020-07-10 13:37:09

标签: flutter

我有以下设置:

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);
  }
  // ...
}

但是,这会崩溃,因为pushReplacement会触发await,而我的应用程序将等到使用pop时才会等待。

如何等待pop的值返回?

更新:

这里的问题比我讲的要复杂一些。

@Alok建议不要pop路由,而应在序列之后进行推送,但是,这是我的代码的一个非常琐碎的版本。

我目前有一个HomeScreen和一个嵌套的Navigator,该嵌套会推送到问题列表。然后,使用Navigator.of(context, rootNavigator: true)导航到examLoadingScreen,依此类推。(您可以在评论中阅读有关内容)

如果在考试完成后按HomeScreen,我将失去在提到的嵌套Navigator中所做的所有导航。

在这种情况下,我非常需要pop。我有多种解决方法,例如pop链接,但是它似乎不太有效或不方便。

1 个答案:

答案 0 :(得分:1)

Zeswen,到目前为止,关于pushReplacementNamed的此文档。它指出=>

通过推入名为routeName的路由并替换最紧密地围绕给定上下文的导航器的当前路由,然后在完成新的动画设置后立即处置先前的路由。 < / p>

您能看到吗,它清楚地提到在完成动画设置后,它会删除前一条路线。

现在,您要实现的目标是 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,它将始终崩溃。

现在,如果要转到页面MainPage,或者在这种情况下,请转到FirstPage。使用pushAndRemoveUntil。基本上,它会删除堆栈中的所有路由,然后转到页面

解决方案::通过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中进行相应的操作,并显示给用户。让我知道是否适合您。

具有最佳解决方案的最新答案

我刚刚添加了这个答案,因为我认为以上内容对将来也很有帮助。

现在,我的想法是基本的,并且根据对我有用的琐碎信息是可行的。

理论:根据该理论,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

如果您不了解图片,请让我帮助您。只要关注您的琐碎数据,希望您能理解其逻辑。实施之后只是步履蹒跚。

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);
  }
}

只要检查一下就告诉我。这种逻辑肯定会帮助您实现目标,它是安全且无错误的:)学习愉快:)