What is the problem? Shared Preferences in LoginScreen does not work every time

-1

I'm trying to do Shared Preferences. It should work so that when the user first logged in and entered his password and his login was transferred to Nome Skreen, the next time he logs into the application he will not need to enter his data and Nome Skreen will immediately open. But at the moment, Shared Preferenses works through time.

I can not get rid of this problem

My code

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


class LoginScreen extends StatefulWidget {
  @override
  LoginScreenState createState() {
    return new LoginScreenState();
  }
}
enum LoginStatus{
  notSignIn,
  signIn,
}

class LoginScreenState extends State<LoginScreen> {
  LoginStatus _loginStatus = LoginStatus.notSignIn;
  var _email, _password;
  bool _obscureText = true;




  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  final FirebaseAuth _auth = FirebaseAuth.instance;
  final GoogleSignIn googleSignIn = GoogleSignIn();
  TextEditingController email = new TextEditingController();
  TextEditingController password = new TextEditingController();
  SharedPreferences sharedPreferences;


  savePref()async{
   SharedPreferences preferences = await SharedPreferences.getInstance();
   setState((){
     preferences.setString('email', _email);
     preferences.setString('password', _password);
     preferences.commit();
   }); 
  }
  var value;
  getPref()async{
    SharedPreferences preferences = await SharedPreferences.getInstance();
    setState(() {
      value = preferences.getString("email");
      value = preferences.getString("password");

      _loginStatus = value == null ? LoginStatus.notSignIn : LoginStatus.signIn;
    });
  }
  @override
  void initState(){
    super.initState();
    getPref();
  }

  @override
  Widget build(BuildContext context) {
    switch(_loginStatus){
      case LoginStatus.notSignIn:
        return Scaffold(
        appBar: AppBar(
          title: Text('Login'),
        ),
        resizeToAvoidBottomPadding: false,
        body: ListView(children: <Widget>[
          Container(
            child: Form(
              key: _formKey,
              autovalidate: true,
              child: Column(
                children: <Widget>[
                  SizedBox(
                    height: 50,
                  ),
                  Padding(
                    child: Image.asset(
                      'images/logo.png',
                      width: 100.0,
                      height: 100.0,
                    ),
                    padding: EdgeInsets.fromLTRB(50, 0, 50, 40),
                  ),
                  Padding(
                    padding: EdgeInsets.fromLTRB(25, 0, 50, 10),
                    child: TextFormField(
                      controller: email,
                      validator: (email) {
                        if (email.isEmpty) {
                          return 'Provide an Email';
                        }
                      },
                      style: TextStyle(
                        color: Color(0xFF01579B),
                        fontSize: 18.0,
                      ),
                      decoration: InputDecoration(
                          border: OutlineInputBorder(
                            borderRadius: BorderRadius.circular(30),
                          ),
                          hintText: 'Enter your Email',
                          labelText: "Email",
                          icon: Padding(
                            padding: EdgeInsets.only(top: 20.0),
                            child: Icon(Icons.email),
                          )),
                      onSaved: (email) => _email = email,
                    ),
                  ),
                  Padding(
                    padding: EdgeInsets.fromLTRB(25, 0, 50, 10),
                    child: TextFormField(
                      controller: password,
                      validator: (password) {
                        if (password.isEmpty) {
                          return 'Provide an password';
                        }
                      },
                      obscureText: _obscureText,
                      style: TextStyle(
                        color: Color(0xFF01579B),
                        fontSize: 18.0,
                      ),
                      decoration: InputDecoration(
                        border: OutlineInputBorder(
                          borderRadius: BorderRadius.circular(30),
                        ),
                        hintText: 'Enter your password',
                        labelText: "Password",
                        icon: Padding(
                          padding: EdgeInsets.only(top: 15.0),
                          child: Icon(Icons.lock),
                        ),
                        suffixIcon: GestureDetector(
                          onTap: () {
                            setState(() {
                              _obscureText = !_obscureText;
                            });
                          },
                          child: Icon(
                            _obscureText
                                ? Icons.visibility
                                : Icons.visibility_off,
                            semanticLabel: _obscureText
                                ? 'show password'
                                : 'hide password',
                          ),
                        ),
                      ),
                      onSaved: (password) => _password = password,
                    ),
                  ),
                  Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        Padding(
                          padding: EdgeInsets.symmetric(horizontal: 10),
                          child: RaisedButton(
                            color: Color(0xFFD50000),
                            textColor: Color(0xFFFFFFFF),
                            child: Text('Login with Google'),
                            onPressed:(){ _signInGoogle().then((FirebaseUser user){
                              print(user);
                            }).catchError((onError){
                              print(onError);
                            });

                            }
                          ),

                        ),
                        Padding(
                          padding: EdgeInsets.symmetric(horizontal: 10),
                          child: RaisedButton(
                            color: Color(0xFF448AFF),
                            textColor: Color(0xFFFFFFFF),
                            child: Text('Login'),
                            onPressed: signIn,
                          ),
                        ),
                  ]),
                      Padding(
                          padding:
                              EdgeInsets.symmetric(horizontal: 10, vertical: 5),
                          child: FlatButton(
                            textColor: Color(0xFF448AFF),
                            child: Text('Forgot Password'),
                            onPressed: () {
                              print('onPressed');
                            },
                          ),
                        ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      Padding(
                        padding: EdgeInsets.fromLTRB(50, 70, 0, 10),
                        child: Text(
                          'Still do not have an account ',
                          style: TextStyle(color: Color(0xFF9E9E9E)),
                        ),
                      ),
                      Padding(
                        padding: EdgeInsets.fromLTRB(0, 70, 30, 10),
                        child: FlatButton(
                          textColor: Color(0xFF448AFF),
                          child: Text('registration'),
                          onPressed: () {
                            Navigator.of(context).pushNamedAndRemoveUntil(
                                '/registration', (Route<dynamic> route) => false);
                          },
                        ),
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ),
        ]),
      );
        break;
      case LoginStatus.signIn:
        return HomeScreen();
        break;
    }

  }
 signIn() async {
    final formState = _formKey.currentState;
    if(formState.validate()) {
      formState.save();
      try {
        FirebaseAuth.instance.signInWithEmailAndPassword(email: _email, password: _password); 

       _loginStatus = LoginStatus.signIn;
      //  savePref(); 
       Navigator.of(context).pushNamedAndRemoveUntil(
                  '/list', (Route<dynamic> route) => false);
      }catch(e){
        print(e.message);
      }
    }
}
Future<FirebaseUser> _signInGoogle() async{
    GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
    GoogleSignInAuthentication gSa =await googleSignInAccount.authentication;

    FirebaseUser user = await _auth.signInWithGoogle(
      idToken: gSa.idToken,
      accessToken: gSa.accessToken
      );
      print('User Name : ${user.displayName}');
      return Navigator.push(context, MaterialPageRoute(builder: (context) => HomeScreen(user: user)));
  }
}
dart
flutter
sharedpreferences

1 Answer

0

You should use a FutureBuilder instead of a normal Build method inside your LoginScreenState because a normal build method will be called before your data is fetched from the Shared Preferences using the async method,unlike the FutureBuilder which will wait for the result to be fetched and set the state of your Stateful widget accordingly. So your code should be like this :

@override
Widget build(BuildContext context) {
return FutureBuilder(
  future: getPref(),
    builder: (BuildContext context, AsyncSnapshot<SharedPreferences> snapshot) {
    if(snapshot.connectionState == ConnectionState.done){

    _loginStatus = snapshot.data.getKeys.length > 0 ? LoginStatus.signIn : LoginStatus.notSignIn ;


      }else{
      return Container() ;
      }
    }
  );
}

this way you'll always get the right login status, after that you can use it for whatever you want to.

answered on Stack Overflow Feb 9, 2019 by Mazin Ibrahim • edited Feb 9, 2019 by Mazin Ibrahim

User contributions licensed under CC BY-SA 3.0