如何检查用户是否已登录,如果是,则显示其他屏幕? [英] How to check if the user is logged in, if so show other screen?

查看:28
本文介绍了如何检查用户是否已登录,如果是,则显示其他屏幕?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的第一个屏幕是登录屏幕,它需要检查用户是否登录才能直接打开主屏幕,但使用此检查时出现错误.

My first screen is a login screen and it needs to check if the user is logged in to open the home screen directly but I get an error using this check.

我正在检查 initState,条件返回 true,所以看起来问题出在导航器上.

I'm doing the check on initState, the condition is returning true, so looks like the problem is with the Navigator.

如果用户已登录,跳过第一个屏幕的正确方法是什么?

What is the correct way to skip the first screen if the user is logged in?

错误:

I/flutter (20803): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter (20803): The following assertion was thrown building Navigator-[GlobalObjectKey<NavigatorState>
I/flutter (20803): _WidgetsAppState#8ce27](dirty, state: NavigatorState#db484(tickers: tracking 2 tickers)):
I/flutter (20803): 'package:flutter/src/widgets/navigator.dart': Failed assertion: line 2106 pos 12: '!_debugLocked':
I/flutter (20803): is not true.
I/flutter (20803): Either the assertion indicates an error in the framework itself, or we should provide substantially
I/flutter (20803): more information in this error message to help you determine and fix the underlying cause.

代码:

class LoginScreen extends StatefulWidget {
  @override
  _LoginScreenState createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {


  final _emailController = TextEditingController();
  final _passController = TextEditingController();

  final _formKey = GlobalKey<FormState>();
  final _scaffoldKey = GlobalKey<ScaffoldState>();

  @override
  void initState() {
    super.initState();

    if(FirebaseAuth.instance.currentUser() != null){

      Navigator.of(context).pushReplacement(MaterialPageRoute(
        builder: (context) => HomeScreen()
      ));
    }

  }


  @override
  Widget build(BuildContext context) {

    return Scaffold(
      key: _scaffoldKey,
      body: ScopedModelDescendant<UserModel>(
          builder: (context, child, model){

            if(model.isLoading)
              return Center(
                child: CircularProgressIndicator(),
              );

            return Form(
              key: _formKey,
              child: ListView(
                padding: EdgeInsets.all(16),
                children: <Widget>[
                  SizedBox(height: 67),
                  Icon(Icons.chrome_reader_mode, size: 150, color: Colors.blue,),
                  SizedBox(height: 16,),
                  TextFormField(
                    controller: _emailController,
                    decoration: InputDecoration(
                        hintText: "Digite seu e-mail",
                        border: OutlineInputBorder(
                            borderRadius: BorderRadius.circular(10),
                        ),
                      fillColor: Colors.blueAccent
                    ),
                    keyboardType: TextInputType.emailAddress,
                    validator: (text){
                      if(text.isEmpty || !text.contains("@"))
                        return "E-mail inválido!";
                    },
                  ),
                  SizedBox(height: 16,),
                  TextFormField(
                    controller: _passController,
                    decoration: InputDecoration(
                        hintText: "Digite sua senha",
                        border: OutlineInputBorder(
                          borderRadius: BorderRadius.circular(10),
                        ),
                        fillColor: Colors.blueAccent
                    ),
                    obscureText: true,
                    validator: (text){
                      if(text.isEmpty || text.length < 6)
                        return "Digite a senha!";
                    },
                  ),
                  SizedBox(height: 16,),
                  FlatButton(
                    padding: EdgeInsets.all(13),
                    shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(10)
                    ),
                    color: Colors.blue,
                      child: Text("Entrar",
                        style: TextStyle(
                          color: Colors.white,
                          fontSize: 20
                        ),
                      ),
                      onPressed: (){

                          if(_formKey.currentState.validate()){

                            model.signIn(

                              email: _emailController.text,
                              pass: _passController.text,
                              onSuccess: _onSuccess,
                              onFail: _onFail,

                            );

                          }


                      },
                  ),
                  SizedBox(height: 10,),
                  InkWell(
                    onTap: (){

                      if(_emailController.text.isEmpty || !_emailController.text.contains("@")){

                        _scaffoldKey.currentState.showSnackBar(
                            SnackBar(content: Text("Insira um e-mail válido para recuperação",
                              style: TextStyle(fontSize: 14),
                            ),
                              backgroundColor: Colors.redAccent,
                              duration: Duration(seconds: 3),
                            )
                        );

                      } else {
                         model.recoverPass(_emailController.text);
                         _scaffoldKey.currentState.showSnackBar(
                           SnackBar(
                             content: Text("O e-mail de recuperação foi enviado!",
                               style: TextStyle(fontSize: 14),
                             ),
                             backgroundColor: Colors.green,
                             duration: Duration(seconds: 3),
                           )
                         );
                      }

                    },
                    child: Text("Esqueci minha senha",
                      style: TextStyle(
                          color: Colors.black,
                          fontSize: 16,
                          fontWeight: FontWeight.w400
                      ),
                      textAlign: TextAlign.center,

                    ),
                  ),
                  SizedBox(height: 30,),
                  InkWell(
                    onTap: (){

                      Navigator.of(context).push(MaterialPageRoute(
                          builder: (context)=> SignUpScreen())
                      );

                    },
                    child: Text("Não tem conta? Cadastre-se!",
                      style: TextStyle(
                        color: Colors.black,
                        fontSize: 16,
                        fontWeight: FontWeight.w600
                      ),
                      textAlign: TextAlign.center,

                    ),
                  ),
                ],
              ),
            );

          },
      ),


    );
  }




}

推荐答案

好吧,您可以使用另一种方法来解决此类问题.而是检查您的 loginScreen 类中是否有用户登录,您可以在此之前执行此步骤,然后决定是否在没有用户登录的情况下显示 loginScreen 或显示另一个屏幕,我假设是 MainScreen,如果用户已经登录.

Well you can solve this kind of problem using another approach. Instead check if there is user logged inside your loginScreen class you can do this a step before and then decide if you will show the loginScreen if there is no user logged or show another screen, MainScreen I' am supposing, if the user is already logged.

我会放一些 snipet 来展示如何做到这一点.我希望它有帮助.但在我解释你的源代码有什么问题之前.

I will put some snipet showing how to accomplish this. I hope it helps. But before I will explain you what is wrong in your source code.

if(FirebaseAuth.instance.currentUser() != null){
      // wrong call in wrong place!
      Navigator.of(context).pushReplacement(MaterialPageRoute(
        builder: (context) => HomeScreen()
      ));
}

你的代码被破坏了,因为 currentUser() 是一个异步函数,当你调用这个函数时,它返回一个不完整的 Future 对象,它是一个非空对象.所以导航器 pushReplacement 总是被调用并且它崩溃了,因为你的小部件的状态还没有准备好.

Your code is broken because currentUser() is a async function and when you make the call this function is returning a incomplete Future object which is a non null object. So the navigator pushReplacement is always been called and it's crashing because the state of your widget is not ready yet.

作为解决方案,您可以使用 FutureBuilder 并决定您将打开哪个屏幕.

Well as solution you can user FutureBuilder and decide which screen you will open.

int main(){
   runApp(  YourApp() )
}

class YourApp extends StatelessWidget{

    @override
    Widget build(BuildContext context){
        return FutureBuilder<FirebaseUser>(
            future: FirebaseAuth.instance.currentUser(),
            builder: (BuildContext context, AsyncSnapshot<FirebaseUser> snapshot){
                       if (snapshot.hasData){
                           FirebaseUser user = snapshot.data; // this is your user instance
                           /// is because there is user already logged
                           return MainScreen();
                        }
                         /// other way there is no user logged.
                         return LoginScreen();
             }
          );
    }
}

使用这种方法可以避免使用 LoginScreen 类来验证是否有用户登录!

Using this approach you avoid your LoginScreen class to verify if there is a user logged!

建议您可以使用 snapshot.connectionState 属性和 switch case 来实现更精细的控制.

As advise you can make use of snapshot.connectionState property with a switch case to implement a more refined control.

这篇关于如何检查用户是否已登录,如果是,则显示其他屏幕?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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