简体   繁体   English

Flutter 和 Firebase 身份验证问题

[英]Flutter and Firebase Authentication problem

Flutter fellow today I have a problem with the Firebase Authentication service. Flutter 小伙伴今天我遇到了 Firebase 身份验证服务的问题。 Well then let me explain the situation.那么我来解释一下情况。 I have a page that let you select a type of user, if you select "Guest" you will push through the app's dashboard page Nav() without sign-in but if select "Sign-in" app will push you to the login page Login() .我有一个页面可以让您选择一种用户类型,如果您选择“访客”,您将在不登录的情况下推送应用程序的仪表板页面Nav()但如果选择“登录”应用程序会将您推送到登录页面Login()

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xFF20348F),
      body: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.end,
          children: [
            Container(
              padding: const EdgeInsets.all(15.0),
              margin: const EdgeInsets.all(15.0),
              alignment: Alignment.center,
              decoration: BoxDecoration(
                color: Colors.amber,
                borderRadius: BorderRadius.circular(45),
              ),
              child: TextButton(
                child: const Text('Guest'),
                onPressed: () {
                  Navigator.pushAndRemoveUntil(
                    context,
                    MaterialPageRoute(
                      builder: (BuildContext context) => const Nav(),
                    ),
                    (route) => false,
                  );
                },
                style: TextButton.styleFrom(
                    primary: const Color(0xFF20348F),
                    textStyle: const TextStyle(
                      fontSize: 30,
                      fontWeight: FontWeight.bold,
                    )),
              ),
            ),
            Container(
              padding: const EdgeInsets.all(15.0),
              margin: const EdgeInsets.all(15.0),
              alignment: Alignment.center,
              decoration: BoxDecoration(
                color: Colors.amber,
                borderRadius: BorderRadius.circular(45),
              ),
              child: TextButton(
                child: const Text('Sign-In'),
                onPressed: () {
                  Navigator.push(context, MaterialPageRoute(builder: (contex) {
                    return const Login();
                  }));
                },
                style: TextButton.styleFrom(
                    primary: const Color(0xFF20348F),
                    textStyle: const TextStyle(
                      fontSize: 30,
                      fontWeight: FontWeight.bold,
                    )),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

In Nav() I use BottomNavigationBarItem and have a several widget included Proflie() inside.Nav()我使用了BottomNavigationBarItem并且里面有一个包含Proflie()小部件。 I already test the sign-up, sign-out and registration function everything is perfectly fine but when I try to be tricky in Proflie() and I face...let's said the weird problem.我已经测试了注册、注销和注册功能,一切都很好,但是当我尝试在Proflie()变得棘手时,我面临......让我们说一个奇怪的问题。 First let's me show you the code in the Proflie() .首先让我向您展示Proflie()的代码。

class Profile extends StatefulWidget {
  const Profile({Key? key}) : super(key: key);
  @override
  _ProfileState createState() => _ProfileState();
}

class _ProfileState extends State<Profile> {
  String? _email;
  DateTime? _creationTime;
  DateTime? _lastSignIn;
  bool? _status;

  @override
  Widget build(BuildContext context) {
    userStatus();
    return userForm();
  }

  userStatus() {
    FirebaseAuth.instance.authStateChanges().listen((event) {
      if (event == null) {
        _status = false;
      } else {
        _status = true;
        _email = FirebaseAuth.instance.currentUser!.email;
        _creationTime =
            FirebaseAuth.instance.currentUser!.metadata.creationTime;
        _lastSignIn =
            FirebaseAuth.instance.currentUser!.metadata.lastSignInTime;
      }
    });
  }

  Widget userForm() {
    if (_status == true) {
      return Scaffold(
        appBar: defaultAppBar('Profile'),
        body: Center(
          child: ListView(
            padding: const EdgeInsets.all(20),
            children: [
              Container(
                margin: const EdgeInsets.all(30),
                child: Text(
                  'Email: $_email',
                  style: const TextStyle(
                      fontSize: 18, fontWeight: FontWeight.bold),
                ),
              ),
              Container(
                margin: const EdgeInsets.all(30),
                child: Text(
                  'Creation Time: $_creationTime',
                  style: const TextStyle(
                      fontSize: 18, fontWeight: FontWeight.bold),
                ),
              ),
              Container(
                margin: const EdgeInsets.all(30),
                child: Text(
                  'Last Sign-In: $_lastSignIn',
                  style: const TextStyle(
                      fontSize: 18, fontWeight: FontWeight.bold),
                ),
              ),
              const SizedBox(height: 45),
              button('Change password', 1),
              const SizedBox(height: 18),
              button('Change email', 2),
              const SizedBox(height: 18),
              button('Sign-out', 0),
            ],
          ),
        ),
      );
    } else {
      return Center(
        child: ListView(
          padding: const EdgeInsets.all(14),
          children: <Widget>[
            const SizedBox(height: 100),
            Container(
              margin: const EdgeInsets.all(30),
              child: const Center(
                child: Text(
                  'Please sign-in to use this Feature',
                  style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                ),
              ),
            ),
            const SizedBox(height: 50),
            button('Login', 3),
            const SizedBox(height: 18),
            button('Register', 4),
          ],
        ),
      );
    }
  }

  Widget button(String txt, int _nav) {
    Color? _color = const Color(0xFF20348F);
    if (_nav == 0) {
      _color = Colors.red;
    }
    return TextButton(
      style: TextButton.styleFrom(
        primary: _color,
        textStyle: const TextStyle(
          fontSize: 20,
        ),
      ),
      child: Text(txt),
      onPressed: () {
        if (_nav == 0) {
          FirebaseAuth.instance.signOut();
          Navigator.pushAndRemoveUntil(
            context,
            MaterialPageRoute(
              builder: (BuildContext context) => const SelectUser(),
            ),
            (route) => false,
          );
        } else {
          Navigator.push(context, MaterialPageRoute(builder: (contex) {
            if (_nav == 1) {
              return const EditPass();
            } else if (_nav == 2) {
              return const EditEmail();
            } else if (_nav == 3) {
              return const Login();
            } else {
              return const Register();
            }
          }));
        }
      },
    );
  }
}

As you can see I'm trying to use userStatus() to identify the "User" and "Guest" and that function I use FirebaseAuth.instance.authStateChanges().listen((event) to check user state in Firebase Authentication(Not really sure am I doing the right way if not please teach me how to check user state) if event == null that mean no user sign-in right now. I'm just going to set _status = false so the "Guest" should found the else case in userForm() . Otherwise _status = true this mean user is signed-in and userForm() should go to if (_status == true) case.正如您所看到的,我正在尝试使用userStatus()来识别“用户”和“访客”,并且该功能我使用FirebaseAuth.instance.authStateChanges().listen((event)来检查 Firebase Authentication(Not真的确定我做对了,如果不是请教我如何检查用户状态)如果event == null意味着现在没有用户登录。我只是要设置_status = false所以“客人”应该在userForm()找到else情况。否则_status = true这意味着用户已登录并且userForm()应该转到if (_status == true)情况。

Now the problem is when I success to sign-in on the Login() .现在的问题是当我成功Login() In Profile() I ended up got the else case of userForm() instead but that not all!Profile()我最终得到了userForm()else情况,但并非全部! When I hot reloaded the IDE it turn out now I'm in the if (_status == true) case.当我热重载 IDE 时,结果现在我处于if (_status == true)情况。 Yeah like said it a weird problem the first time that app loaded the page it go to false case but when hot reloaded it turn to true case.是的,就像在应用程序第一次加载页面时说这是一个奇怪的问题,它会变成错误的情况,但是当热重新加载时,它会变成真实的情况。 I'm not so sure the error is from Profile() or Login() .我不太确定错误来自Profile()Login() I'm just going leave the Login() then.那我就要离开Login()

class Login extends StatefulWidget {
  const Login({Key? key}) : super(key: key);

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

class _LoginState extends State<Login> {
  final _formKey = GlobalKey<FormState>();

  var _email = "";
  var _password = "";

  final emailController = TextEditingController();
  final passwordController = TextEditingController();

  bool _passwordVisible = true;

  @override
  void dispose() {
    emailController.dispose();
    passwordController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return formLogin();
  }

  Widget formLogin() {
    return Scaffold(
      appBar: defaultAppBar('Sign-In'),
      body: Center(
        child: Form(
          key: _formKey,
          child: Padding(
            padding: const EdgeInsets.all(32),
            child: ListView(
              children: [
                buildEmail(),
                const SizedBox(height: 24),
                buildPassword('Password', 'Your password...'),
                const SizedBox(height: 50),
                button('Sign-in', 0),
                const SizedBox(height: 24),
                button('Sign-up', 1),
              ],
            ),
          ),
        ),
      ),
    );
  }

  userLogin() async {
    try {
      await FirebaseAuth.instance
          .signInWithEmailAndPassword(email: _email, password: _password);
      Navigator.pushAndRemoveUntil(
        context,
        MaterialPageRoute(
          builder: (BuildContext context) => const Nav(),
        ),
        (route) => false,
      );
    } on FirebaseAuthException catch (e) {
      if (e.code == 'user-not-found') {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(
            backgroundColor: Colors.amber,
            content: Text(
              "Email not found",
              style: TextStyle(fontSize: 16.0, color: Colors.black),
            ),
          ),
        );
      } else if (e.code == 'wrong-password') {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(
            backgroundColor: Colors.amber,
            content: Text(
              "Password incorrect",
              style: TextStyle(fontSize: 16.0, color: Colors.black),
            ),
          ),
        );
      }
    }
  }

  TextButton button(String txt, int nav) {
    return TextButton(
      style: TextButton.styleFrom(
        primary: const Color(0xFF20348F),
        textStyle: const TextStyle(
          fontSize: 20,
        ),
      ),
      child: Text(txt),
      onPressed: () {
        if (nav == 0) {
          if (_formKey.currentState!.validate()) {
            setState(() {
              _email = emailController.text;
              _password = passwordController.text;
            });
            userLogin();
          }
        } else {
          _formKey.currentState!.reset();
          Navigator.push(context, MaterialPageRoute(builder: (contex) {
            return const Register();
          }));
        }
      },
    );
  }

  Widget buildEmail() {
    return TextFormField(
      decoration: const InputDecoration(
        labelText: 'Email',
        hintText: 'name@example.com',
        prefixIcon: Icon(Icons.mail_outline),
        border: OutlineInputBorder(),
        errorStyle: TextStyle(color: Colors.redAccent, fontSize: 15),
      ),
      controller: emailController,
      validator: MultiValidator([
        RequiredValidator(errorText: "Email is required"),
        EmailValidator(errorText: "The format of email is incorrect")
      ]),
      keyboardType: TextInputType.emailAddress,
      textInputAction: TextInputAction.done,
    );
  }

  Widget buildPassword(String _txt1, String _txt2) {
    return TextFormField(
      obscureText: _passwordVisible,
      decoration: InputDecoration(
        labelText: _txt1,
        hintText: _txt2,
        suffixIcon: GestureDetector(
          onTap: () {
            setState(() {
              _passwordVisible = !_passwordVisible;
            });
          },
          child: Icon(
            _passwordVisible ? Icons.visibility : Icons.visibility_off,
          ),
        ),
        prefixIcon: const Icon(Icons.vpn_key_outlined),
        border: const OutlineInputBorder(),
        errorStyle: const TextStyle(color: Colors.redAccent, fontSize: 15),
      ),
      controller: passwordController,
      validator: RequiredValidator(errorText: "Password is required"),
      textInputAction: TextInputAction.done,
    );
  }
}

If you guy could help me I'd gladly appreciated.如果你能帮助我,我将不胜感激。

如果您可以创建一个 .gist,我会对您有所帮助,同样在您的个人资料页面中,我可以看到您在构建中监听用户更改的问题,将其添加到构建中非常不切实际,因为 flutter 会调用构建方法多次,构建应该是干净的,也有潜在的内存泄漏,因为你没有处理流。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM