You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter应用Stream初始状态异常及Google登录后用户名不显示问题

解决你的Google登录Stream状态与UI更新问题

嘿,刚上手Dart和Flutter的第一个应用对吧?我帮你梳理下遇到的两个问题,咱们一步步来解决:

问题1:初始Stream状态为ConnectionState.waiting而非none

你现在的_currentUser变量一开始是未初始化的(默认null),当StreamBuilder拿到null的stream时,就会默认进入ConnectionState.waiting状态。要让初始状态变成none,咱们只需要在初始化的时候给_currentUser赋值一个空的Stream就行。

问题2:登录成功后无法立即显示用户名

你点击登录按钮时直接给_currentUser赋值了新的Stream,但没有触发Widget的重建——Flutter只有在调用setState的时候才会重新执行build方法更新UI,所以你的StreamBuilder根本没机会监听新的用户数据流,自然不会显示用户名。咱们需要把赋值操作放到setState里。

修改后的完整代码

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

final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn _googleSignIn = GoogleSignIn();

class HomePage extends StatefulWidget {
  static String tag = 'home-page';

  @override
  HomePageState createState() {
    return HomePageState();
  }
}

class HomePageState extends State<HomePage> {
  // 初始化空Stream,让初始状态为ConnectionState.none
  Stream<FirebaseUser> _currentUser = Stream.empty();

  Future<FirebaseUser> signInWithGoogle() async {
    print('google signin invoked');
    GoogleSignInAccount googleUser = await _googleSignIn.signIn();
    GoogleSignInAuthentication googleAuth = await googleUser.authentication;
    FirebaseUser user = await _auth.signInWithGoogle(
      accessToken: googleAuth.accessToken,
      idToken: googleAuth.idToken,
    );
    print("signed in " + user.displayName);
    return user;
  }

  @override
  Widget build(BuildContext context) {
    final lblWelcome = Padding(
      padding: EdgeInsets.all(8.0),
      child: Text('Frnds Payment', style: TextStyle(fontSize: 28.0, color: Colors.green))
    );

    final btnSignin = MaterialButton(
      child: const Text('Sign In with Google'),
      onPressed: () async {
        print('button clicked');
        // 用setState触发UI更新,让StreamBuilder监听新的Stream
        setState(() {
          _currentUser = signInWithGoogle().asStream();
        });
      }
    );

    final txtOutput = StreamBuilder<FirebaseUser>(
      stream: _currentUser,
      builder: (BuildContext context, AsyncSnapshot<FirebaseUser> snapshot) {
        switch (snapshot.connectionState) {
          case ConnectionState.none:
            // 初始状态会走到这里,显示提示文字或者空布局
            return Text('请点击按钮登录');
          case ConnectionState.waiting:
            return Center(child: CircularProgressIndicator());
          default:
            if (snapshot.hasError) 
              return Text('Error: ${snapshot.error}');
            else 
              return Center(child: Text('欢迎你,${snapshot.data.displayName}'));
        }
      }
    );

    final body = Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[lblWelcome, btnSignin, txtOutput],
      ),
    );

    return Scaffold(body: body);
  }
}

关键修改点说明

  • 初始化Stream:把Stream<FirebaseUser> _currentUser;改成Stream<FirebaseUser> _currentUser = Stream.empty();,这样初始时StreamBuilder的connectionState就是none,你可以在这个状态下显示“请点击按钮登录”之类的提示,比加载圈更友好。
  • 用setState更新Stream:在登录按钮的onPressed里,把_currentUser = signInWithGoogle()?.asStream();放到setState回调里,这样Flutter会知道状态变了,重新构建Widget,StreamBuilder就能拿到新的用户数据并显示用户名了。

这样修改后,你打开应用初始状态会显示提示文字,点击登录后显示加载圈,登录成功后立刻显示用户名,完全符合你的需求啦~

内容的提问来源于stack exchange,提问作者Rahul Somasundaram

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:17:45