问题描述
用Navigator.popUntil(context,ModalRoute.withName(name));返回时闪退,报错信息类似 '!_debugLocked': is not true
问题定位
'package:flutter/src/widgets/navigator.dart': Failed assertion: line 2247 pos 12: '!_debugLocked': is not true.
先进入navigator.dart,错误在这里
Widget build(BuildContext context) {
assert(!_debugLocked);
}
看下定义
bool _debugLocked = false; // used to prevent re-entrant calls to push, pop, and friends
阻止重复调用,也就是说,在某个动作完成前再一次调用的时候。网上也有类似的issue,用了延时的方法解决的,通过实验发现,这个并不是我闪退的原因,继续找看下popUntil的定义
static void popUntil(BuildContext context, RoutePredicate predicate) {
Navigator.of(context).popUntil(predicate);
}
---------------------------分割线---------------------------
void popUntil(RoutePredicate predicate) {
while (!predicate(_history.last))
pop();
}
emmm,看下RoutePredicate predicate是什么
static RoutePredicate withName(String name) {
return (Route<dynamic> route) {
return !route.willHandlePopInternally
&& route is ModalRoute
&& route.settings.name == name;
};
}
对当前rote做判断是否是即将pop的,与所要寻找的name相同,是否是ModalRoute,这里主要看route.settings.name == name,是否正确,就是说当前stack 即_history中不存在与name相同的route时就会一直pop,再来看pop方法
if (_history.length > 1) {
_history.removeLast();
// If route._navigator is null, the route called finalizeRoute from
// didPop, which means the route has already been disposed and doesn't
// need to be added to _poppedRoutes for later disposal.
if (route._navigator != null)
_poppedRoutes.add(route);
_history.last.didPopNext(route);
for (NavigatorObserver observer in widget.observers)
observer.didPop(route, _history.last);
RouteNotificationMessages.maybeNotifyRouteChange(_routePoppedMethod, route, _history.last);
} else {
assert(() { _debugLocked = false; return true; }());
return false;
}
在遍历到最后一个发现也不是所要寻找的route时就会走else方法,造成_debugLocked = false,之后就报错了。。 经过验证,只要Navigator.popUntil(context,ModalRoute.withName(name))中的name是_history的任何一个都不会闪退,看来问题就是在这里了,果然是源码之下,任何问题都无所遁形,所以说学会看源码还是很重要的