用了手势监听的方式返回上一页,为什么不直接用BackButton,里面也调用了路由ma ymaybePop为什么点击没反应

来源:6-7 如何创建和使用Flutter的路由与导航?【边学边做】

IT小菜

2019-05-14

写回答

1回答

CrazyCodeBoy

2019-05-15

首先检查一下BackButton所在页面是不是被MaterialApp组件包裹了呢,被MaterialApp包裹的页面是无法通过BackButton组件返回到上一页的,将外层的MaterialApp去掉即可:

 @override
 Widget build(BuildContext context) {
   return MaterialApp(
       ...
       home: Scaffold(
           appBar: AppBar(
           title: Text('BackButton点击没反应'),
             leading: BackButton(),
           ),
          ...
 }
//改成
@override
 Widget build(BuildContext context) {
   return Scaffold(
       appBar: AppBar(
         title: Text('BackButton点击没反应'),
         leading: BackButton()//外层不能有MaterialApp,
       ),
     ...
     }

BackButton被点击的时候会调用maybePop进行返回:

@optionalTypeArgs
Future<bool> maybePop<T extends Object>([ T result ]) async {
 final Route<T> route = _history.last;
 assert(route._navigator == this);
 final RoutePopDisposition disposition = await route.willPop();
 if (disposition != RoutePopDisposition.bubble && mounted) {
   if (disposition == RoutePopDisposition.pop)
     pop(result);
   return true;
 }
 return false;
}

接下来说下一原理:

在上述代码中:

final RoutePopDisposition disposition = await route.willPop();

当BackButton被点击时,会通过route.willPop()决定是否可以返回到上一页,这里我们先看一下willPop()到底做了什么:

Future<RoutePopDisposition> willPop() async {
   return isFirst ? RoutePopDisposition.bubble : RoutePopDisposition.pop;
}

willPop会判断当前页面是不是处于栈顶(当前MaterialApp中的第一个页面),如果是则返回RoutePopDisposition.bubble,所以说只有当前页面不是MaterialApp中的第一个页面时才能通过maybePop返回到上一页,在上述案例中,BackButton被放在了MaterialApp下的第一个页面中所以会出现BackButton点击无效的问题。

接下来在扩充下maybePop与pop的区别,它们的不同之处在于maybePop会多了一步向系统询问是否处理当前返回操作,当Route.willPop返回值为RoutePopDisposition.bubble时即交给系统处理,这里也简单介绍RoutePopDisposition三个枚举值:

  • pop 弹出路由,正常情况返回上一级

  • doNotPop 不弹出,沉默处理,很多时候出现在一些表单填写的情况,必须完成页面内容,或者提示用户点击第二次才能退出

  • bubble 交给系统处理,一般直接退出应用

简单来讲,pop()要比maybePop()的功能更强大些,pop()不管当前页面是不是处于栈顶都会使当前页面关闭,也可以返回到上一个MaterialApp中的页面,而maybePop()只能返回当前MaterialApp中的上一个页面。

注意:pop()这么强大但它有个副作用,如果当前页面已经处于栈顶并且前面没有其他MaterialApp的时候,调用pop()你会看到黑屏,这是因为在这种情况下pop()将应用中的唯一的一个页面关闭导致的,所以为了防止这个问题可以在调用pop()之前通过Navigator.canPop(context)判断下是不是还可以返回。


2
1
IT小菜
非常感谢!谢谢老师,等我学到断点那一课时我在断点到源码里看看
2019-05-15
共1条回复

Flutter从入门到进阶 实战携程网App 一网打尽核心技术

解锁Flutter开发新姿势,,系统掌握Flutter开发核心技术。

4788 学习 · 3270 问题

查看课程