Flutter:StreamBuilder快照-无数据 [英] Flutter: StreamBuilder Snapshot -- No Data

查看:129
本文介绍了Flutter:StreamBuilder快照-无数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习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上.

顺便说一句,如果我显示登录屏幕代替进度指示器,则代码有效.因此,我显然不了解整个流初始化过程.

有人可以向我解释我在哪里错了吗?预先感谢一百万.

正如您提到的,解决方案

当流初始化时,它发出null,但是当用户未登录时,它也发出null,这就是为什么steam认为没有data(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(),
            ),
         );
    }

I am just learning Flutter and am trying to use a StreamBuilder to display a Login / Register page if the user is logged out, or a Profile page if the user is logged in. My code is below:

Auth Service:

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(),
            ),
          );
        }
      },
    );
  }

It was my understanding the stream would begin emitting 'null' once it was initialized, and would continue doing so until it fired off an Auth state change...

But the snapshot continually reports "No Data" and thus my code is stuck on the CircularProgressIndicator.

BTW, if I display the log-in screen in place of the progress indicator, the code works. So I'm clearly not understanding the whole stream initialization process.

Can somebody kindly explain to me where I have gone wrong here? Thanks a million in advance.

解决方案

As you mention, as stream initialise it emits null but when user is not login then also it emits null, which steam consider as no data(null) that’s why this error is happening.

you can use Streambuilder's connection state to differentiate between no user null and null after initialisation.

I hope following code help you.

  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(),
            ),
         );
    }

这篇关于Flutter:StreamBuilder快照-无数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆