【问题标题】:StreamBuilder not work when enter to the page again再次进入页面时StreamBuilder不工作
【发布时间】:2020-02-11 14:18:58
【问题描述】:

首先提前感谢,我尝试创建一个应用程序并尝试使用它,首先我在应用程序中管理用户的状态登录,为此我使用本指南https://fireship.io/lessons/flutter-firebase-google-oauth-firestore/该应用程序按预期工作登录页面中的 facebook 登录(observable 发出一个新值并使用 StreamBuilder 创建相应的小部件一切正常!),但是当我按下返回按钮到其他页面并再次进入登录页面时,与 StreamBuilder 小部件关联的流返回因此 null 再次显示 formLogin(要注册的表单)小部件而不是配置文件小部件(显示用户信息的小部件),或者我使用错误的 streamBuilder 任何建议都很好。

我放代码

再次提前感谢

Login Widget(用于管理登录和用户信息的小部件)和 AuthService(用于登录的逻辑)

  ProfilePage({Key key}) : super(key: key);

  _ProfilePageState createState() => _ProfilePageState();
}

class _ProfilePageState extends State<ProfilePage>
    with TickerProviderStateMixin {
  var opacity = true;
  AnimationController _controller;
  Animation<double> _animation;
  bool _loading = false;
  final GlobalKey<FormState> _formKeyLogin = GlobalKey<FormState>();
  final GlobalKey<FormState> _formKeyLogup = GlobalKey<FormState>();
  final PageController _pageController = PageController();
  int _typeForm = 0;
  // int currentPage = 1;

  @override
  void initState() {
    super.initState();

    _controller = AnimationController(
        vsync: this, duration: Duration(milliseconds: 1500));

    _animation = CurvedAnimation(
      parent: _controller,
      curve: Curves.decelerate,
    );

    _controller.forward();

    authService.loading.listen((state) => setState(() => _loading = state));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Stack(
          children: <Widget>[
            StreamBuilder(
              stream: authService.profile,              
              builder: (context, snapshot) {
                if (snapshot.hasData) {
                  User user = User.mapFromMap(snapshot.data);
                  return new FormProfile(loading: _loading, user: user);
                } else {
                  return new FormLogin(
                      animation: _animation,
                      loading: _loading,
                      pageController: _pageController,
                      formKeyLogin: _formKeyLogin,
                      formKeyLogup: _formKeyLogup);
                }
              },
            )
          ],
        ),
      ),
    );
  }
}




    class AuthService {
  final GoogleSignIn _googleAuth = GoogleSignIn();
  final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
  final Firestore _firestore = Firestore.instance;
  bool isAdmin = false;

  Observable<FirebaseUser> user; //FirebaseUser instance
  Observable<Map<String, dynamic>> profile; //database's user info
  PublishSubject loading = PublishSubject();

  AuthService() {
    user = Observable(_firebaseAuth.onAuthStateChanged);
    profile = user.switchMap((FirebaseUser u) {
      if (u != null) {
        return _firestore
            .collection("users")
            .document(u.uid)
            .snapshots()
            .map((snap) => snap.data);
      } else {
        return Observable.just(null);
      }
    });
  }

  Future<FirebaseUser> facebookLogin() async {
    loading.add(true);
    final facebookLogin = FacebookLogin();
    final result = await facebookLogin.logInWithReadPermissions(['email']);
    FirebaseUser user;
    switch (result.status) {
      case FacebookLoginStatus.loggedIn:
        final AuthCredential credential = FacebookAuthProvider.getCredential(
            accessToken: result.accessToken.token);
        try {
          user = await _firebaseAuth.signInWithCredential(credential);
          await validateAccount(user);
          updateUserData(user);
        } on PlatformException catch (e) {
          switch (e.code) {
            case Strings.AUTH_CONST_ERROR_INVALID_CREDENTIAL:
              Utilities.showToast(
                  Strings.AUTH_CONST_ERROR_INVALID_CREDENTIAL_MSG,
                  Toast.LENGTH_LONG,
                  2);
              break;
            case Strings.AUTH_CONST_ERROR_USER_DISABLED:
              Utilities.showToast(Strings.AUTH_CONST_ERROR_USER_DISABLED_MSG,
                  Toast.LENGTH_LONG, 2);
              break;
            case Strings
                .AUTH_CONST_ERROR_ACCOUNT_EXISTS_WITH_DIFFERENT_CREDENTIAL:
              Utilities.showToast(
                  Strings
                      .AUTH_CONST_ERROR_ACCOUNT_EXISTS_WITH_DIFFERENT_CREDENTIAL_MSG,
                  Toast.LENGTH_LONG,
                  2);
              break;
            case Strings.AUTH_CONST_ERROR_OPERATION_NOT_ALLOWED:
              Utilities.showToast(
                  Strings.AUTH_CONST_ERROR_OPERATION_NOT_ALLOWED_MSG,
                  Toast.LENGTH_LONG,
                  2);
              break;
            case Strings.AUTH_CONST_ERROR_INVALID_ACTION_CODE:
              Utilities.showToast(
                  Strings.AUTH_CONST_ERROR_INVALID_ACTION_CODE_MSG,
                  Toast.LENGTH_LONG,
                  2);
              break;
            default:
              Utilities.showToast(Strings.AUTH_CONST_ERROR_GENERAL_CODE_MSG,
                  Toast.LENGTH_LONG, 2);
          }
        }
        break;
      case FacebookLoginStatus.cancelledByUser:
        break;
      case FacebookLoginStatus.error:
        Utilities.showToast(result.errorMessage, Toast.LENGTH_SHORT, 2);
        //_showErrorOnUI(result.errorMessage);
        break;
    }

    loading.add(false);
    return user;
  }


final AuthService authService = AuthService();

【问题讨论】:

标签: flutter


【解决方案1】:

您的问题可能源于您使用的是 Observables 而不是 Streams,或者在加载对象的情况下是 PublishSubject。正如rxdart Observable class 在此处记录的那样,Observables 是单一订阅的 - 根据您的描述,您已经在应用程序的其他位置收到了来自此订阅的数据。

考虑使用一个多订阅的广播流 (Observable asBroadcastStream),另一个 PublishSubject(本质上是一个广播),或者如果你不特别喜欢使用 Observables,你可以用标准的 Dart Streams 替换它们,在这种情况下,您的界面可能如下所示:

BehaviorSubject<FirebaseUser> _user; //Or PublishSubject
Sink<Map<String, dynamic>> get inProfile => _user.sink; // call .add() to inProfile to add new data
Stream<Map<String, dynamic>> get outProfile => _user.stream; // attach this to your Streambuilder output

【讨论】:

  • 嗨,肖恩,验证主页中的代码我验证并存在其他订阅 authService.profile .listen((data) =&gt; {_isSignIn = (data != null) ? true : false}); 如果我删除该行它有效,我将尝试更改 Observable 的类以多次订阅配置文件(这是问题的可观察原因,而不是用户获取更多信息)谢谢我会验证
猜你喜欢
  • 2015-12-09
  • 1970-01-01
  • 2011-08-02
  • 1970-01-01
  • 2015-01-23
  • 2021-01-30
  • 1970-01-01
  • 2022-06-17
  • 2019-08-03
相关资源
最近更新 更多