Flutter:StreamBuilder 快照——无数据
Posted
技术标签:
【中文标题】Flutter:StreamBuilder 快照——无数据【英文标题】:Flutter: StreamBuilder Snapshot -- No Data 【发布时间】: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 上。
顺便说一句,如果我显示登录屏幕代替进度指示器,代码就可以工作。所以我显然不了解整个流初始化过程。
有人可以向我解释我在哪里出错了吗?提前一百万谢谢。
【问题讨论】:
【参考方案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(),
),
);
,
);
【讨论】:
以上是关于Flutter:StreamBuilder 快照——无数据的主要内容,如果未能解决你的问题,请参考以下文章
Flutter:将firestore快照转换为streambuilder中的列表
在 Flutter 中从 Firebase FireCloud 接收数据时,StreamBuilder 中的快照代码不会被执行
Flutter StreamBuilder中使用的Firestore快照在数据更改时永远不会更新