我有一个特殊的用例,现在让我头痛了几个小时。
我确实有一个使用 Firebase 和社交登录进行身份验证的应用程序。此外,我实现了 redux 来管理应用程序状态。
一切都像这样工作正常,但只有当我在需要来自 FirebaseUser
的数据的屏幕上尝试注销时类渲染将失败,因为导航器的转换仍在运行(触发我导航离开的屏幕的重新渲染)并最终在所需的位置结束,但在转换时屏幕出现故障。
我的中间件代码是这样的:
Middleware<RootState> _signOutUser(GlobalKey navigatorKey) {
return (Store<RootState> store, dynamic dynamicAction, NextDispatcher next) {
final SignOut action = dynamicAction;
final NavigatorState nav = navigatorKey.currentState;
next(action);
store.dispatch(AppIsLoading());
Future<dynamic>(() async {
try {
await auth.signOut();
} on PlatformException catch (error) {
return Future<void>.error(error);
}
}).then<void>((dynamic _) {
nav.pushNamedAndRemoveUntil(Routes.home, (Route<dynamic> route) => false);
store.dispatch(UnsetUser());
store.dispatch(AppIsLoaded());
action.completer.complete();
}).catchError((Object response) {
nav.maybePop(nav.context);
action.completer.completeError(response);
store.dispatch(AppIsLoaded());
});
};
}
理想情况下,我会这样做:
Middleware<RootState> _signOutUser(GlobalKey navigatorKey) {
return (Store<RootState> store, dynamic dynamicAction, NextDispatcher next) {
final SignOut action = dynamicAction;
final NavigatorState nav = navigatorKey.currentState;
next(action);
store.dispatch(AppIsLoading());
Future<dynamic>(() async {
try {
await auth.signOut();
} on PlatformException catch (error) {
return Future<void>.error(error);
}
}).then<void>((dynamic _) {
return nav.pushNamedAndRemoveUntil(Routes.home, (Route<dynamic> route) => false);
}).then<void>((dynamic _) {
store.dispatch(UnsetUser());
store.dispatch(AppIsLoaded());
action.completer.complete();
}).catchError((Object response) {
nav.maybePop(nav.context);
action.completer.completeError(response);
store.dispatch(AppIsLoaded());
});
};
}
但是这种方式也可以在过渡时进行渲染。
我可以只在屏幕上添加保护,但这会导致屏幕看起来不像我刚刚看到的那样。
或者小部件内部是否有一种方法可以防止在特殊事件中重新渲染,以便它保持原样?
我有点迷失了 atm,所以任何帮助表示赞赏。
谢谢!
最佳答案
我找到了解决方案......它显然是 flutter
中的一个错误框架。
我在 Navigator
中挖掘和 NavigatorState
flutter 包的类,找到了 Future 从未完成的原因。
方法pushNamedAndRemoveUntil
(以及其他几个)确实返回一个完成者。到目前为止,它是(有点)正确的。但它仅在 Route
时完成从堆栈中弹出。这是不正确的行为。
就我而言,它应该在新 Route 被推送到堆栈时完成(并且过渡/动画完成)。实际上,Route 上存在一种方法,名为 didPush
它从动画返回一个 TickerFuture:
TickerFuture didPush() => TickerFuture.complete();
这与我对这样的方法的期望一样多。
现在我直接在包中修复了它,但之后会提交一个问题,以便将来修复。
关于flutter:WAITING导航过渡结束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58833991/