我是Flutter的新手,正在尝试通过登录和注册来构建身份验证系统。
我遵循了在线教程,一切正常。但是我的身份验证流程略有不同,并且当我添加额外的步骤时,“登录”或“注册”屏幕请勿重定向到首页登录页面。
这是教程中的代码,可以正常工作。您会注意到,启动应用程序时,出现的第一个屏幕是Wrapper.dart
通过IF STATE调用的登录。
这里是教程中的文件:
教程main.dart
void main() {
runApp(Main());
}
class Main extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamProvider<User>.value(
value: AuthService().user,
child: MaterialApp(
home: Wrapper(),
debugShowCheckedModeBanner: false,
)
);
}
}
教程wrapper.dart
class Wrapper extends StatelessWidget {
@override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
// return either Home or Auth widget
if (user == null) {
return Authenticate();
} else {
return Home();
}
}
}
教程authenticate.dart
class Authenticate extends StatefulWidget {
@override
_AuthenticateState createState() => _AuthenticateState();
}
class _AuthenticateState extends State<Authenticate> {
bool showSignIn = true;
void toggleView() {
setState(() => showSignIn = !showSignIn);
}
@override
Widget build(BuildContext context) {
if (showSignIn) {
return SignIn(toggleView: toggleView);
} else {
return Register(toggleView: toggleView);
}
}
}
教程signIn.dart
class SignIn extends StatefulWidget {
final Function toggleView;
SignIn({this.toggleView});
@override
_SignInState createState() => _SignInState();
}
class _SignInState extends State<SignIn> {
final AuthService _auth = AuthService();
final _formKey = GlobalKey<FormState>();
bool loading = false;
// text Field State
String email = '';
String password = '';
String error = '';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.brown[400],
elevation: 0.0,
title: Text('Sign in'),
actions: <Widget>[
FlatButton.icon(
icon: Icon(Icons.person),
label: Text('Register'),
onPressed: () {
widget.toggleView();
},
)
]),
body: Container(
padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 50.0),
child: Form(
key: _formKey,
child: Column(children: <Widget>[
SizedBox(height: 20.0),
TextFormField(
decoration: textInputDecoration.copyWith(hintText: 'Email'),
validator: (val) => val.isEmpty ? 'Enter an email' : null,
onChanged: (val) {
setState(() => email = val);
},
),
SizedBox(height: 20.0),
TextFormField(
obscureText: true,
decoration:
textInputDecoration.copyWith(hintText: 'Password'),
validator: (val) => val.length < 6
? 'Password is too short. Min 6 characters long'
: null,
onChanged: (val) {
setState(() => password = val);
},
),
SizedBox(height: 20.0),
RaisedButton(
color: Colors.pink[400],
child: Text(
'Sign in',
style: TextStyle(color: Colors.white),
),
onPressed: () async {
if (_formKey.currentState.validate()) {
setState(() => loading = true);
dynamic result = await _auth.signInWithEmailAndPassword(
email, password);
if (result == null) {
setState(() {
error =
'These credentials are invalid. Please check them and try again!';
loading = false;
});
}
}
},
),
]))
));
}
}
Registration.dart
文件与SignIn
类似,因此在此不再显示。
最后要记录的文件是名为 AuthService.dart
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
// Create user object based on FirebaseUser
User _userFromFirebaseUser(FirebaseUser user) {
return user != null ? User(uid: user.uid) : null;
}
// Auth change user stream
Stream<User> get user {
return _auth.onAuthStateChanged.map(
_userFromFirebaseUser); // This is the equivalent of .map((FirebaseUser user) => _userFromFirebaseUser(user));
}
// SignIn with Email & Password
Future signInWithEmailAndPassword(String email, String password) async {
try {
AuthResult result = await _auth.signInWithEmailAndPassword(
email: email, password: password);
FirebaseUser user = result.user;
return _userFromFirebaseUser(user);
} catch (e) {
print(e.toString());
return null;
}
}
}
让我解释一下以上流程的工作原理
用户启动应用程序时,main.dart
文件将调用wrapper.dart
,该文件将检查User是否为空或存在。
如果为User=null
,则表示它尚未登录并调用Authenticate.dart
,默认情况下会打开SignIn
屏幕。
如果为User != null
,则表示用户已登录并调用Home.dart
屏幕。
******我的问题*****
现在,在我的流程中(见下文),Wrapper
在StartAuthButtons.dart
时调用User=null
。
StartAuthButtons
有几个按钮,可通过不同的方法(例如Google,Facebook,Apple和通过电子邮件/密码)对用户进行身份验证。
MY Wrapper.dart :
class Wrapper extends StatelessWidget {
@override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
if (user == null) {
return StartAuthButtons();
//return Authenticate(); <-- this was before
} else {
return Home();
}
}
}
一旦用户单击“使用电子邮件和密码登录”,我将使用Flutter Navigate
进入“登录”页面。这是我与本教程不同的额外步骤。 (请在星号之间的以下代码中检查我的评论)
我的 StartAuthButtons.dart
class StartAuthButtons extends StatefulWidget {
@override
_StartAuthButtonsState createState() => _StartAuthButtonsState();
}
class _StartAuthButtonsState extends State<StartAuthButtons> {
final AuthService _auth = AuthService();
@override
Widget build(BuildContext context) {
return Stack(children: [
AuthLayout(),
Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
title: Center(child: Text('Welcome')),
backgroundColor: Colors.transparent,
),
body: SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
//Email & Password SignIn
Padding(
padding: EdgeInsets.all(8.0), child: new MaterialButton(
child: SignInEmailPasswordBtn(),
onPressed: () {
****** I THINK THE ISSUE IS HERE *********
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Authenticate()),
);
*** As you can see above, here is where I call Authenticate() ***
****** But by adding this extra step to reach the SignIn page, when I signin it doesn't redirect to the Home once signed in. It stays on the SignIn screen. If I hard refresh the app, the system is logged in **********
}
)
)
]
)
)
)
))]);
}
}
使用Navigate
小部件进入SignIn
页面后,登录后似乎无法进入Home
屏幕成功。
身份验证工作正常,因为如果我强制刷新该应用程序,它将显示为登录用户的Home
屏幕。
似乎onPress
要进行身份验证,在Home
和StartAuthButton
之间进行选择的IF STATEMENT不会被触发。
我们非常感谢您的帮助。 很抱歉使用长脚本。 乔
答案 0 :(得分:0)
感谢@Unbreachable建议您查看有关弹出和推送的文章。
我对d = dict.fromkeys(df.columns.difference(['type1','type2']), 'max')
d['type3'] = 'first'
d['val1'] = 'last'
df = df.groupby(["type1","type2"], as_index=False, sort=False).agg(d)
print (df)
type1 type2 type3 val1 val2 val3
0 a b q 4 6 7
1 a c w 2 5 8
2 b c t 2 9 0
和SignIn
小部件进行了简单的更改。这两个小部件都提交了onPress按钮。
之前的代码:
Register
及之后:
onPressed: () async {
if (_formKey.currentState.validate()) {
setState(() => loading = true);
dynamic result = await _auth.registerWithEmailAndPassword(email, password);
if (result == null) {
setState(() {
error = 'Email or password are invalid.';
loading = false;
});
}
}
},
现在,加载工作正常,当消失时,我可以看到onPressed: () async {
if (_formKey.currentState.validate()) {
setState(() => loading = true);
dynamic result = await _auth.registerWithEmailAndPassword(email, password);
if (result == null) {
setState(() {
error = 'Email or password are invalid.';
loading = false;
});
} else {
Navigator.of(context).pop(); <-- here the change.
loading = false; <-- here the change.
}
}
},
小部件。