dart - 问题是什么?LoginScreen 中的共享首选项并非每次都有效
问题描述
我正在尝试执行共享首选项。它应该可以在用户首次登录并输入密码并将登录信息转移到 Nome Skreen 时,在下次登录应用程序时无需输入数据,Nome Skreen 将立即打开。但目前,共享偏好会随着时间的推移而发挥作用。
我无法摆脱这个问题
我的代码
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)));
}
}
解决方案
您应该在您的内部使用 aFutureBuilder
而不是普通Build
方法,因为在从using方法LoginScreenState
获取数据之前将调用普通构建方法,这与它将等待获取结果并相应地设置小部件状态的方法不同。所以你的代码应该是这样的:Shared Preferences
async
FutureBuilder
Stateful
@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() ;
}
}
);
}
这样,您将始终获得正确的登录状态,之后您可以随意使用它。
推荐阅读
- php - 遍历相邻列表
- docker - Docker 卷未同步
- python - 如何使用python清空Sqlite3上的单元格
- java - 如何将Map的相似值汇总在一起
- sql - 将一列拆分或 Substr 为多列
- java - 范围“请求”对当前线程无效;在消息监听器中
- python-3.x - Python3.5 异步执行类似于Java-SpringBoot @EnableAsync @Async 注解
- ruby-on-rails - 在另一个视图中显示 f.select 值
- python - 使用 Pip Install 安装 Python 库“Boto3”时出错
- python - tf.GradientTape() 的 __exit__ 函数的参数是什么?