再次进入页面时,StreamBuilder无法正常工作

时间:2019-10-15 00:16:02

标签: flutter

首先,首先要感谢,我尝试创建一个应用程序,并尝试将其与flutter一起使用,首先,我在应用程序内部管理了用户的状态登录,为此,我按照本指南https://fireship.io/lessons/flutter-firebase-google-oauth-firestore/的要求使用该应用程序预期在登录页面中使用Facebook登录(observable发出新值,并使用StreamBuilder创建相应的小部件,一切正常!),但是当我按下返回按钮到其他页面并再次输入登录页面时,与StreamBuilder关联的流小部件返回null,从而再次显示formLogin(要注册的表单)小部件,而不是个人资料小部件(小部件,以显示用户信息),或者我错误地使用了streamBuilder,任何建议都得到了很好的接受。

我输入了代码

再次感谢

登录小部件(用于管理登录和用户信息的小部件)和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();

1 个答案:

答案 0 :(得分: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