有没有办法避免在 Flutter 的 Navigator _history 中出现重复?
Posted
技术标签:
【中文标题】有没有办法避免在 Flutter 的 Navigator _history 中出现重复?【英文标题】:Is there a way to avoid duplicates in the Navigator _history in Flutter? 【发布时间】:2020-11-20 06:45:35 【问题描述】:所以我有一个应用程序,比如说,它只包含一个主屏幕、一个配置文件屏幕和一个购物篮屏幕。从主/主屏幕,我可以访问其他两个屏幕。实际上,我可以通过侧边栏访问所有这三个屏幕。 如果我在调试模式下启动应用程序,我可以如下导航:
HomeScreen -> ProfileScreen -> HomeScreen (over sidebar) -> Profile Screen.
所有这些都是通过 Navigator.pushNamed() 完成的。这意味着,导航器的 _history 堆栈具有:
主屏幕 个人资料屏幕 主屏幕 个人资料屏幕这有点愚蠢,它使用 RAM 而无需这样做。 我可以通过每次进入 HomeScreen 时使用 popUntil() 来解决这个问题,这样我就有了一个新的历史记录,但如果我这样做就无济于事了:
HomeScreen -> ProfileScreen -> BasketScreen (over sidebar) -> Profile Screen (over sidebar) -> BasketScreen (over sidebar).
如何从历史记录中删除 RIGHT 屏幕,最好不要制作自己的导航器?有可能吗?我的意思是,理想情况下,Navigator 在最后一个示例之后的历史应该是这样的:
主屏幕 个人资料屏幕 篮子屏幕(意思是如果调用了 BasketScreen,它会从历史记录中删除所有先前的 BasketScreen,等等)
还是一开始就允许这样的循环调用只是我的错误?虽然我怀疑我是唯一一个这样使用侧边栏的人。
【问题讨论】:
我想如果您担心它,您可以在推送之前查看 pop。您可以覆盖页面路由以抑制弹出动画,使其看起来类似于您之前的 ***.com/questions/49874272/… 您可以在调用 pushNamed() 之前移除Route(routeName)。如果页面不存在(在您的情况下可以忽略),它会引发错误。但是,这样一来,您的任何页面都无法利用弹出页面传递的值,因为它们已被释放。 @NavaneethP 遗憾的是,我太笨了,无法在典型上下文之外使用 removeRoute 。我们正在使用一个额外的类“ScreenController”来管理路由转换,但我不知道如何获取 removeRoute 所需的第二个参数(Route我最近遇到了同样的问题,此外我有可能稍后需要删除路线。要解决重复页面的问题,只需使用
Navigator.pushReplacementNamed(context, name)
而不是
Navigator.pushNamed(context, name)
如果您需要更多的路由控制和上下文,唯一真正的方法是创建一个自定义 NavigatorObserver,将其添加到您的 MaterialApp,然后在需要删除页面时引用它(就像您尝试在没有实际出现在 Navigator 历史记录中的情况下删除路线,它会抛出错误)。这个 NavigatorObserver 应该适用于大多数用途。
需要注意的一点是,您似乎无法删除 NavigatorObserver 内的路由,因为它似乎在进行更改时将自己锁定为更改。
class Observatory extends NavigatorObserver
List<Route> routeHistory = List();
@override
void didPush(Route route, Route previousRoute)
routeHistory.add(route);
super.didPush(route, previousRoute);
@override
void didPop(Route route, Route previousRoute)
routeHistory.removeLast();
super.didPop(route, previousRoute);
@override
void didRemove(Route route, Route previousRoute)
var beginIndex = routeHistory.indexOf(route);
var endIndex = routeHistory.indexOf(previousRoute);
if((endIndex == -1 && beginIndex != -1) || beginIndex -1 == endIndex)
routeHistory.remove(route);
else if(endIndex != -1 && beginIndex != -1)
routeHistory.removeRange(beginIndex,endIndex);
super.didRemove(route, previousRoute);
@override
void didReplace(Route newRoute, Route oldRoute)
if(routeHistory.contains(oldRoute))
routeHistory[routeHistory.indexOf(oldRoute)] = newRoute;
super.didReplace(newRoute: newRoute, oldRoute: oldRoute);
bool containsRoute(Route route) => routeHistory.contains(route);
现在每当我需要删除路线时,我都会这样做
if(observatory.containsRoute(route))
Navigator.remove(context, route);
【讨论】:
对于我的项目,我通过制作一个自定义导航器“修复”了这个问题,该导航器每次用户进入主屏幕时都会清空自身(或其堆栈)。由于用户最终会到达那里,所以这不是什么大问题。 ^^'以上是关于有没有办法避免在 Flutter 的 Navigator _history 中出现重复?的主要内容,如果未能解决你的问题,请参考以下文章
Flutter 中的 pushReplacementNamed 和 popAndPushNamed 有啥区别?
有没有办法在 Flutter 的 TabBar 中创建下拉列表?