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

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

问题描述

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

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.

我将简要介绍如何完成此操作。希望对您有所帮助。但是在我向您解释源代码中出什么问题之前。

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对象,该对象是一个非null的对象。因此,导航器 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 属性与切换情况以实现更精细的控制。

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

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

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