flutter:等待导航转换结束

Mic*_*len 5 dart flutter

我有一个特殊的用例,现在让我头疼了好几个小时。

我确实有一个使用 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());
    });
  };
}
Run Code Online (Sandbox Code Playgroud)

理想情况下我会这样做:

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());
    });
  };
}
Run Code Online (Sandbox Code Playgroud)

但通过这种方式,也会在过渡时进行渲染。

我可以在屏幕上添加防护装置,但这会导致屏幕看起来不像我刚刚看到的那样。

或者小部件内部是否有一种方法可以防止在特殊事件中重新渲染,以便它保持原来的样子?

我有点丢了自动取款机,所以非常感谢您的帮助。

谢谢!

Mig*_*ivo 0

正如您现在所拥有的那样,获得所需的结果可能非常棘手,因为您正在等待注销(其中FirebaseUser删除),然后推送到新屏幕。

问题是,与此同时,一旦您删除用户,您仍然需要当前屏幕上的一些数据(我相信?),并且您会在转换过程中遇到异常,因为您正在尝试访问以下数据:目前不可用。我对吗?

一种简单的解决方案(也许是最正确的解决方案)是让您注销的屏幕中对用户的引用一直存在,直到其生命周期结束,因此,仅在处置时将其删除。我们无权访问您的小部件,但您可以创建一个变量来获取用户引用,然后注销将注销用户,但您仍然可以通过小部件上的该引用访问以前的数据。

另一种解决方案是仅在推送到新屏幕后注销,但是如果由于某种原因注销失败,您将无法正确回退,但是,通常客户端上的这种注销是以尽力而为的方法进行的,无论是否失败,它总是会为用户注销。因此,通过这种方式,您可以简单地await从 the 中删除signOut,因为它将同步结束该方法并随后调用退出,或者您可以使其更明确,如下所示:

   try {
      await nav.pushNamedAndRemoveUntil(
      Routes.home, (Route<dynamic> route) => false).then((_) => auth.signOut());
      store.dispatch(UnsetUser());
      store.dispatch(AppIsLoaded());
      action.completer.complete();
    } on PlatformException catch (error) {
      var response = await Future<void>.error(error);
      await nav.maybePop(nav.context);
      action.completer.completeError(response);
      store.dispatch(AppIsLoaded());
    }
Run Code Online (Sandbox Code Playgroud)