首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Flutter和GoRouter的Streambuilder持久化用户状态

使用Flutter和GoRouter的Streambuilder持久化用户状态
EN

Stack Overflow用户
提问于 2022-11-18 07:33:22
回答 1查看 56关注 0票数 1

以前有人使用Streambuilder和Flutter和GoRouter来保持用户状态吗?

目前,我正在使用默认的颤振导航,它运行良好(参见下面),但我现在正尝试用GoRouter替换

我以前使用默认颤振导航的导航设置

代码语言:javascript
复制
home: StreamBuilder(
           stream: AuthMethods().authChanges,
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(
              child: CircularProgressIndicator(),
               );
             }

             if (snapshot.hasData) {
               return const TabsScreen();
            }

            return const AuthScreen();
           }),
    );
   }

我现在的goRouter代码。我想知道在哪里可以使用以下d代码中的Streambuilder来持久化我的应用程序的用户状态(或者Streambuilder是否可以与go路由器一起使用)

代码语言:javascript
复制
GoRouter routeConstruct() {
  return GoRouter(
    routes: <RouteBase>[
      GoRoute(
          path: '/',
          builder: (BuildContext context, GoRouterState state) {
            return const PublicScreen();
          },
          routes: <RouteBase>[
            GoRoute(
              path: Events_Screen,
              builder: (BuildContext context, GoRouterState state) {
                return const EventsScreen();
              },
            ),
            GoRoute(
              path: "$EventDetail_Screen/:eventId",
              builder: (BuildContext context, GoRouterState state) {
                return EventDetailScreen(eventId: state.params['eventId']!);
              },
            ),
            ...
          ]),
    ],
  );

我能否使用Streambuilder和GoRouter来持久化用户身份验证状态?如果可以,在goRouter代码中,我可以在哪里使用Streambuilder来根据Auth状态确定要显示哪个小部件?谢谢

###########################

类AuthMethods

代码语言:javascript
复制
class AuthMethods {
  final FirebaseAuth _auth = FirebaseAuth.instance;
  final FirebaseFirestore _firestore = FirebaseFirestore.instance;

  Stream<User?> get authChanges => _auth.authStateChanges();
// --> use of bang ! operator here
  User get user => _auth.currentUser!;

  Future<bool> signInWithGoogle(BuildContext context) async {
    bool res = false;

    try {
      final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();
      final GoogleSignInAuthentication? googleAuth =
          await googleUser?.authentication;

      final credential = GoogleAuthProvider.credential(
          accessToken: googleAuth?.accessToken, idToken: googleAuth?.idToken);

      UserCredential userCredential =
          await _auth.signInWithCredential(credential);

      User? user = userCredential.user;

      if (user != null) {
        if (userCredential.additionalUserInfo!.isNewUser) {
          await _firestore.collection('users').doc(user.uid).set({
            'username': user.displayName,
            'uid': user.uid,
            'profilePhoto': user.photoURL,
          });
        }
        res = true;
      }
    } on FirebaseAuthException catch (e) {
      showSnackBar(context, e.message!);
      res = false;
    }
    return res;
  }

类RouteNotifier

代码语言:javascript
复制
class RouterNotifier extends ChangeNotifier {
  RouterNotifier(this._authMethods) {
    _authMethods.authChanges.listen((event) {
      notifyListeners();
    });
  }

  final AuthMethods _authMethods;

  String? redirect(BuildContext context, GoRouterState state) {
    final onLoginPage = state.location == '/$AuthScreen';
    final onHomePage = state.location == '/$Tabs_Screen';

// --> The getter 'isEmpty' isn't defined for the type 'User'.
// --> User get user => _auth.currentUser!; used a bang operator
    if (_authMethods.user.isEmpty && onHomePage) {
      return '/$AuthScreen';
    }

// --> The getter 'isEmpty' isn't defined for the type 'User'.
    if (_authMethods.currentUser.isNotEmpty && onLoginPage) {
      return '/$Tabs_Screen';
    }

    return null;
  }
}

router.dart

代码语言:javascript
复制
GoRouter routeConstruct() {
  return GoRouter(
    refreshListenable: router,

    routes: <RouteBase>[
      GoRoute(
          path: '/',
          builder: (BuildContext context, GoRouterState state) {
            return const PublicScreen();
          },
          routes: <RouteBase>[
            GoRoute(
              path: Events_Screen,
              builder: (BuildContext context, GoRouterState state) {
                return const EventsScreen();
              },
            ),
            GoRoute(
              path: "$EventDetail_Screen/:eventId",
              builder: (BuildContext context, GoRouterState state) {
                return EventDetailScreen(eventId: state.params['eventId']!);
              },
            ),
          ]),
    ],
  );
}
EN

回答 1

Stack Overflow用户

发布于 2022-11-18 11:38:02

在go路由器5.0.0之前:

go路由器有一个名为GoRouterRefreshStream的类,所以在go路由器中

代码语言:javascript
复制
GoRouter (
....
refreshListenable: GoRouterRefreshStream(AuthMethods().authChanges),

但是在go路由器5.0.0之后,它们是移除

因此,您必须创建自己的通知程序:

代码语言:javascript
复制
class RouterNotifier extends ChangeNotifier {


  RouterNotifier(this._authMethods) {
    _authMethods.authChanges.listen((event) {
      notifyListeners();
    });
  }

  final AuthMethods _authMethods;
}

围棋路由器:

代码语言:javascript
复制
GoRouter(
      debugLogDiagnostics: false,
      ....
      ...
      refreshListenable: RouterNotifier(AuthMethods()),
      ...
      );

go路由器如何像以前使用的流生成器那样工作呢?

重定向派上用场:

代码语言:javascript
复制
final router  = RouterNotifier(AuthMethods());

GoRouter (
...
refreshListenable: router,
redirect: router.redirect,

RouterNotifier类中:

代码语言:javascript
复制
class RouterNotifier extends ChangeNotifier {
    
    
      RouterNotifier(this._authMethods) {
        _authMethods.authChanges.listen((event) {
          notifyListeners();
        });
      }
    
      final AuthMethods _authMethods;

    String? redirect(BuildContext context, GoRouterState state) {

    final onLoginPage = state.location == '/login';
    final onHomePage = state.location == '/';

    if (_authMethods.currentUser.isEmpty && onHomePage) {

      return '/login';
    }

    if (_authMethods.currentUser.isNotEmpty && onLoginPage) {

      return '/';
    }


    return null;
  }

}

类用户模型:

代码语言:javascript
复制
class User {

String id;
.........
some variable i need from db;

static const empty = User(id: '');

bool get isEmpty => this == User.empty;
bool get isNotEmpty => this != User.empty;

}

在溪流上:

代码语言:javascript
复制
Stream<User> get user {
    // map the user if user null is mean empty
    return _firebaseAuth.authStateChanges().asyncMap((fUser) async {
      
      if (fUser == null) {
      const User user = User.empty;
      return user;
      } else {
      // in my case i need to take some data from Firestore 
      .... 
      await datafromDb() // if you dont need to wait future, remove async map, just use normal map
      return fUser.withBiodata();
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74486264

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档