【问题标题】:Flutter: StreamBuilder Snapshot -- No DataFlutter:StreamBuilder 快照——无数据
【发布时间】:2020-08-23 12:06:11
【问题描述】:

我刚刚学习 Flutter,并尝试使用 StreamBuilder 在用户注销时显示登录/注册页面,或者在用户登录时显示个人资料页面。我的代码如下:

认证服务:

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';

class AuthUser {
  AuthUser({@required this.uid, @required this.email});
  final String uid;
  final String email;
}

abstract class AuthBase {
  Future<AuthUser> currentUser();
  Future<AuthUser> signIn({String email, String pw});
  Future<AuthUser> registerUser({String email, String pw});
  Stream<AuthUser> get onAuthStateChanged;
  Future<void> signOut();
}

class Auth implements AuthBase {
  final _firebaseAuth = FirebaseAuth.instance;

  AuthUser _userFromFirebase(FirebaseUser user) {
    if (user != null) {
      return AuthUser(uid: user.uid, email: user.email);
    } else {
      return null;
    }
  }

  @override
  Stream<AuthUser> get onAuthStateChanged {
    return _firebaseAuth.onAuthStateChanged.map(_userFromFirebase);
  }

  @override
  Future<AuthUser> currentUser() async {
    final user = await _firebaseAuth.currentUser();
    return _userFromFirebase(user);
  }

  @override
  Future<AuthUser> signIn({String email, String pw}) async {
    final authResult = await _firebaseAuth.signInWithEmailAndPassword(email: email, password: pw);
    return _userFromFirebase(authResult.user);
  }

  @override
  Future<AuthUser> registerUser({String email, String pw}) async {
    final authResult = await _firebaseAuth.createUserWithEmailAndPassword(email: email, password: pw);
    return _userFromFirebase(authResult.user);
  }

  @override
  Future<void> signOut() async {
    await _firebaseAuth.signOut();
  }
}

StreamBuilder:

class WelcomeScreen extends StatelessWidget {
  WelcomeScreen({@required this.auth});
  static const String id = '/';
  final AuthBase auth;

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<AuthUser>(
      stream: auth.onAuthStateChanged,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          AuthUser user = snapshot.data;
          if (user == null) {
            return displayLoginOrRegPage(context);
          } else {
            return ProjectScreen(
              user: user,
              auth: auth,
            );
          }
        } else {
          return Scaffold(
            body: Center(
              child: CircularProgressIndicator(),
            ),
          );
        }
      },
    );
  }

据我了解,流一旦初始化就会开始发出“null”,并且会继续这样做,直到它触发 Auth 状态更改...

但快照不断报告“无数据”,因此我的代码卡在 CircularProgressIndicator 上。

顺便说一句,如果我显示登录屏幕代替进度指示器,代码就可以工作。所以我显然不了解整个流初始化过程。

有人可以向我解释我在哪里出错了吗?提前一百万谢谢。

【问题讨论】:

    标签: flutter stream stream-builder


    【解决方案1】:

    正如您所提到的,当stream 初始化时它会发出null,但是当用户没有登录时,它仍然会发出null,stream 认为没有数据即null 这就是错误的原因.

    您可以使用Streambuilder的连接状态来区分无用户null和初始化后的null。

    希望下面的代码对你有所帮助。

      if (snapshot.connectionState == ConnectionState.active) {
            if (snapshot.data == null) {
                   return displayLoginOrRegPage(context);
             } else {
                AuthUser user = snapshot.data;
                   return ProjectScreen(
                        user: user,
                        auth: auth,
                    ); 
               }
        } else {
             return Scaffold(
                 body: Center(
                 child: CircularProgressIndicator(),
                ),
             );
        }
    

    【讨论】:

    • 这是一个很好的提示。我现在不在我的开发机器上,但我明天一定会检查一下。我确定这是我正在寻找的答案,当我确认时我会这样标记。提前谢谢!
    【解决方案2】:

    尝试将 WelcomeScreen 更改为完整的 Widget。

    【讨论】:

    • 在我重构它以使用 StreamBuilder 之前,我的代码是一个有状态的小部件。它现在没有状态逻辑,所以我努力摆脱它。我很确定@viren-v-varasadiya 有正确的答案。不过谢谢!
    【解决方案3】:

    根据@VirenVVarasadiya,这绝对是一个检查 ConnectionState 的案例。这是最终的工作代码。谢谢!

      @override
      Widget build(BuildContext context) {
        return StreamBuilder<AuthUser>(
          stream: auth.onAuthStateChanged,
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.active) {
              if (snapshot.data != null) {
                AuthUser user = snapshot.data;
                return ProjectScreen(
                  user: user,
                  auth: auth,
                );
              } else {
                return displayLoginOrRegPage(context);
              }
            } else {
              return Scaffold(
                body: Center(
                  child: CircularProgressIndicator(),
                ),
              );
            }
          },
        );
      }
    

    【讨论】:

      猜你喜欢
      • 2017-07-27
      • 1970-01-01
      • 2023-04-10
      • 2018-12-05
      • 1970-01-01
      • 2016-12-28
      • 2020-09-10
      • 2019-03-03
      • 2020-03-19
      相关资源
      最近更新 更多