onPopPage 和 route.didPop

来源:7-6 实战--实现页面导航管理(四)

demonCry

2022-09-08

Navigator(
   key: navigatorKey,
   // 通过一个list来保存的 但其实还是一个栈的结构 只不过我们能通过list的特性来交换里面页面的顺序
   pages: List.of(_pages),

   //Called when [pop] is invoked but the current [Route] corresponds to a [Page] found in the [pages] list.
   onPopPage: _onPopPage,
 );

bool _onPopPage(Route route, dynamic result){
  if(!route.didPop(result)) return false; 

  if(_canPop()){
    _pages.removeLast();
    return true;
  } else {
    return false;
  }
}
  1. onPopPage 是在我们调用 Navigator.pop(context,true) 或 我们自定义的 router.popRoute 时候调用的吗?
  2. 这里调用 route.didPop 是干什么的 ?
  3. _onPopPage 里返回 true 和 false 有什么意义?区别?
  4. Navigator.pop(context,true) 第二个参数写true和false又有什么区别?
写回答

1回答

马超老师

2022-09-10

1、注意onPopPage是在创建Navigator的时候传入的,所以只有在调用Navigator.pop之后,此时系统会回调onPopPage函数。故自定义的router.popRoute是不会触发onPopPage回调的;

2、route里面didpop方法的作用是在底层路由栈中弹出指定页面,如果弹出成功则返回true,此时我们在pages列表中同步移除该页面;如果系统弹出失败则返回false(特殊情况才会),那么我们的pages也保持不变,直接return即可。

(扩展知识:通常情况下我们需要保持系统底层路由栈和我们的pages一致,如果不一致系统就会以当前pages为准,将多余的page当做新页面,再生成一个新的route对象,这样做的目的还是要保持底层路由栈中的内容上层 pages 数据一致,这里主要是需要注意要同步更新pages即可


3、onPopPage的返回值表示是否允许当前页面弹出。返回true则顺利退出,返回false页面不会弹出。

这个是为了解决早期Navigator的使用问题。这样可以让页面是否关闭完全由开发者掌控,而不是单纯地交给系统的Navigator.pop()。

当你在某种场景下(比如页面栈只有最后一个页面)不希望Navigator弹出页面的时候,可以在onPopPage回调中返回false阻止返回。你可以尝试一下, 如果把onPopPage返回值改成false,然后调用Navigator.pop(),是没办法返回页面的。

4、Navigator.pop()的第二个参数是一个泛型类型,用于在弹出页面的时候给上一个页面返回值。项目中是点确认返回true,点取消返回false。当然也可以根据实际业务场景返回其他类型变量。


可能第二点当中的路由栈维护会有点不好理解,这里可以简单理解为,在系统移除页面后需要同步更新pages列表的状态。其他的还有解释不清楚的欢迎留言。

0
0

基于Flutter 3.x 实战跨平台仿抖音App混合开发

以短视频APP为例,快速上手原生/Flutter 混合开发

481 学习 · 120 问题

查看课程