【问题标题】:Using FirebaseAuth to Skip Login Screen for Logged In Users Flutter使用 FirebaseAuth 跳过登录用户的登录屏幕 Flutter
【发布时间】:2024-05-19 20:40:02
【问题描述】:

我正在尝试使用 FirebaseAuth 跳过登录页面并直接进入我的应用程序的主页,但 firebaseAuth.getCurrentUser() 给出了两次结果,第一次是 null,第二次是 FirebaseUser。并且应用程序总是将第一个结果作为THE 结果,这给了我登录屏幕。

我的代码如下;

@override
  Widget build(BuildContext context) {
    return FutureBuilder<FirebaseUser>(
        future: authService.getCurrentUser(),
        builder: (context, AsyncSnapshot<FirebaseUser> snapshot) {
          print("snapshot data");
          print(snapshot.hasData);
          if (snapshot.hasData) {
            print(snapshot.data.uid);
            return MaterialApp(
              theme: ThemeData(
                primarySwatch: Colors.blue,
              ),
              initialRoute: HomePage.id,
              routes: {
                HomePage.id: (context) => HomePage(snapshot.data.uid),
                WelcomePage.id: (context) => WelcomePage(),
                RegistrationPage.id: (context) => RegistrationPage()
              },
            );
          } else {
            return SafeArea(
              child: Scaffold(
                backgroundColor: colorPalette.white,
                body: Padding(
                  padding: EdgeInsets.symmetric(horizontal: 20.0),
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: <Widget>[
                      Padding(
                        padding: EdgeInsets.symmetric(horizontal: 20.0),
                        child: SizedBox(
                          height: 150,
                          child: Image.asset(
                            "lib/assets/images/logo-with-name.png",
                          ),
                        ),
                      ),
                      Padding(
                        padding: EdgeInsets.symmetric(
                            horizontal: 20.0, vertical: 10.0),
                        child: CustomTextBox(
                          size: 8.0,
                          hintText: "E-Mail",
                          borderColor: colorPalette.logoLightBlue,
                          function: onChangeFunction,
                          keyboardType: TextInputType.emailAddress,
                        ),
                      ),
                      Padding(
                        padding: EdgeInsets.symmetric(
                            horizontal: 20.0, vertical: 10.0),
                        child: CustomTextBox(
                          size: 8.0,
                          hintText: "Password",
                          borderColor: colorPalette.logoLightBlue,
                          function: onChangeFunctionTwo,
                          keyboardType: TextInputType.text,
                        ),
                      ),
                      Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: <Widget>[
                          Padding(
                            padding: EdgeInsets.only(
                                left: 10.0, top: 10.0, bottom: 10.0),
                            child: Material(
                              elevation: 5.0,
                              color: colorPalette.lighterPink,
                              borderRadius: BorderRadius.circular(10.0),
                              child: MaterialButton(
                                onPressed: () {
                                  signIn();
                                },
                                child: Text(
                                  "Log In",
                                  style: TextStyle(
                                    color: colorPalette.white,
                                  ),
                                ),
                              ),
                            ),
                          ),
                          Padding(
                            padding: const EdgeInsets.all(10.0),
                            child: Text("or"),
                          ),
                          GestureDetector(
                            onTap: () {
                              setState(() {
                                Navigator.pushNamed(
                                    context, RegistrationPage.id);
                              });
                            },
                            child: Text(
                              "Register",
                              style: TextStyle(
                                fontWeight: FontWeight.bold,
                                color: colorPalette.logoLightBlue,
                              ),
                            ),
                          ),
                        ],
                      )
                    ],
                  ),
                ),
              ),
            );
          }
        });
  }

AuthService 类;

class AuthService {
  final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;

  Stream<String> get onAuthStateChanged => _firebaseAuth.onAuthStateChanged.map(
        (FirebaseUser user) => user?.uid,
      );

  // Email & password Sign Up
  Future<String> createUser(String email, String password, String companyName,
      String nameAndSurname) async {
    try {
      final currentUser = await _firebaseAuth.createUserWithEmailAndPassword(
          email: email, password: password);

      // Update the UserName
      var userUpdate = UserUpdateInfo();
      userUpdate.displayName = companyName;

      await currentUser.user.updateProfile(userUpdate);

      await currentUser.user.reload();

      Firestore.instance.runTransaction((Transaction transaction) async {
        await Firestore.instance.collection("users").add({
          currentUser.user.uid: {
            "properties": {
              "companyName": companyName,
              "nameAndSurname": nameAndSurname,
              "eMail": email,
              "currentCashBalance": 0,
              "currentTotalBalance": 0,
            },
            "partners": {},
            "revenues": {},
            "payments": {}
          }
        });
      });

      return currentUser.user.uid;
    } catch (err) {
      if (err is PlatformException) {
        if (err.code == "ERROR_EMAIL_ALREADY_IN_USE") {
          return "ERROR_EMAIL_ALREADY_IN_USE";
        } else {
          return err.code;
        }
      }
    }
  }

  // Email & password Sign In
  Future<String> signInWithEmailAndPassword(
      String email, String password) async {
    return (await _firebaseAuth.signInWithEmailAndPassword(
            email: email, password: password))
        .user
        .uid;
  }

  // Sign Out
  signOut() {
    return _firebaseAuth.signOut();
  }

  // Get Current User
  Future<FirebaseUser> getCurrentUser() async {
    FirebaseUser user = await _firebaseAuth.currentUser();
    return user;
  }
}

应用启动时的结果是这样的:

I/flutter (12529): snapshot data
I/flutter (12529): false
I/flutter (12529): snapshot data
I/flutter (12529): true
I/flutter (12529): *firebase userid*

我在这里做错了什么,我该如何改正?

【问题讨论】:

    标签: android firebase flutter firebase-authentication


    【解决方案1】:
        //function to check if the user is logged in
    Future getCurrentUser() async {
            FirebaseUser _user = await FirebaseAuth.instance.currentUser();
            print("User: ${_user?.email ?? "None"}");
            print(_user);
            return _user;
          }
    //using future builder to show whichever screen you want to show loading screen is 
    //empty screen with circular progress indicator in center i hope this will help you
         home: FutureBuilder(
                  future: getCurrentUser(),
                  builder: (context, snapshot) {
                    if (snapshot.connectionState == ConnectionState.waiting) {
                      return LoadingScreen();
                    } else if (snapshot.connectionState == ConnectionState.done) {
                      return snapshot.data == null ? LoginScreen() : MainScreen();
                    }
                    return LoginScreen();
                  },
                ),
    

    【讨论】:

      【解决方案2】:

      你得到这个的原因是因为builder在检索userid之前被执行。

      因此您需要使用CircularProgressIndicator(),这将显示循环进度,直到检索到future 的结果。例如:

      builder: (context, snapshot) {
          if (snapshot.hasData) {
            return Text(snapshot.data.uid);
          } else if (snapshot.hasError) {
            return Text("${snapshot.error}");
          }
      
          // By default, show a loading spinner.
          return CircularProgressIndicator();
        },
      );
      

      【讨论】:

      • 如果snapshot 有数据,这只会显示HomePage。如果snapshot 没有 有任何数据,我还想显示WelcomePage。简而言之,我希望我的代码确保getCurrentUser() 不会返回任何id,然后返回WelcomePage。现在,FutureBuilder 无论用户是否登录,都会首先返回WelcomePage,然后理论上如果用户登录,则显示HomePage
      • 这将只显示CircularPogressIndicator 直到future 完成,您可以保留 if else 但这将保证未来完成,现在它可以更轻松地执行 if 块或否则阻止
      • @oividiosCaeremos 请检查dartpad.dartlang.org/896fa75be39ef3abab49f77b2a6855f5 以了解我的意思。这正是你想要的!!先CircularPogressIndicator ,如果uid返回false就进入登录,如果返回true就可以进入欢迎界面
      • Peter 我明白你的意思,但我的snapshot 只能返回两件事。有没有用户。我尝试了您的解决方案,但它不起作用,因为snapshot 从来没有errors,因此永远不会返回Scaffold,它有Login Page。感谢您的回复和努力,但它不适用于我的情况。