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

Flutter中Google SignIn验证后传用户邮箱至其他页面的实现疑问

Hey there! Let's break down your problem and fix this properly. Your current setup has a few key issues—like the Scaffold not waiting for mostraUID() to finish, and calling setState() directly in build() which can trigger infinite loops. Let's tackle this step by step using Flutter's best practices for async operations and Firebase Auth.


1. Using Future/Async for Authentication Logic

Your mostraUID() function is on the right track, but relying on a one-time Future in initState isn't the most reliable way. A better approach is to listen to Firebase Auth's user state stream—this automatically updates your UI whenever the user logs in, logs out, or their credentials change, which is far more robust than a single async call.

2. Making Scaffold Wait for Authentication

Instead of trying to "wait" for mostraUID() to complete, we'll use StreamBuilder to build the UI conditionally based on the authentication state. This lets us show a loading state until user data is ready, then switch to the appropriate UI (login prompt or logged-in view).

3. Optimal Implementation

Here's a refactored version of your code that solves all your issues, including safely getting the user's email for your Firebase database reference:

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

final googleSignIn = GoogleSignIn();
final auth = FirebaseAuth.instance;

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  // Dedicated async function for Google Sign-In
  Future<void> _signInWithGoogle() async {
    try {
      final GoogleSignInAccount? googleUser = await googleSignIn.signIn();
      if (googleUser == null) return; // User canceled the sign-in flow

      final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
      final AuthCredential credential = GoogleAuthProvider.credential(
        accessToken: googleAuth.accessToken,
        idToken: googleAuth.idToken,
      );

      await auth.signInWithCredential(credential);
      // No manual state updates needed—StreamBuilder handles UI changes automatically
    } catch (e) {
      print('Sign-in error: $e');
      // Add a snackbar or alert here to notify the user of the error
    }
  }

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    // Use StreamBuilder to listen to real-time auth state changes
    return StreamBuilder<FirebaseUser>(
      stream: auth.onAuthStateChanged, // Emits current user when state updates
      builder: (context, snapshot) {
        // Handle loading state while checking auth status
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const Scaffold(
            body: Center(child: CircularProgressIndicator()),
          );
        }

        // User is not logged in—show login prompt
        if (!snapshot.hasData || snapshot.data == null) {
          return Scaffold(
            appBar: AppBar(title: Text(widget.title)),
            body: const Center(child: Text('Please log in to continue')),
            floatingActionButton: FloatingActionButton(
              onPressed: _signInWithGoogle,
              tooltip: 'Sign in with Google',
              child: const Icon(Icons.login),
            ),
          );
        }

        // User is logged in—access their data safely
        final FirebaseUser user = snapshot.data!;
        final String userEmail = user.email ?? 'No email found';
        
        // Now you can safely use userEmail to build your Firebase database reference
        // Example: final databaseRef = FirebaseDatabase.instance.reference().child('messages/$userEmail');

        return Scaffold(
          appBar: AppBar(
            title: Text(userEmail), // Display user's email in the app bar
          ),
          body: Center(
            child: Text('Button tapped $_counter time${_counter == 1 ? '' : 's' }.'),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _incrementCounter,
            tooltip: 'Increment',
            child: const Icon(Icons.add),
          ),
        );
      },
    );
  }
}

Key Improvements:

  • No global state: We removed the global _loggedUser variables (they're unnecessary and can cause inconsistent state) and get user data directly from the StreamBuilder snapshot.
  • Real-time updates: The auth.onAuthStateChanged stream automatically refreshes the UI when the user logs in/out or their account changes—no manual state management needed.
  • Proper state handling: We show a loading indicator while checking auth status, a login prompt if the user isn't authenticated, and the main UI once logged in.
  • Safe data access: Null checks (?? 'No email found') handle cases where the user's email might be missing.
  • Cleaner code: Sign-in logic is isolated to a dedicated function, making the code easier to maintain and debug.

Quick Tips for Flutter/Firebase Beginners:

  • Never call setState() inside build()—this triggers an infinite loop because build() runs every time state changes.
  • For newer Firebase versions, use auth.authStateChanges() instead of onAuthStateChanged (it's the updated API).
  • If you need to fetch additional data from Firebase Database once the user is logged in, nest a FutureBuilder inside the logged-in section of the StreamBuilder.

内容的提问来源于stack exchange,提问作者Colque Paxi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:36:27