大家好,我在 flutter 中遇到了一个奇怪的错误,当我尝试登录时,它不会将我重定向到我的经过身份验证的页面(状态不会更新),但它保持原样,它只会重定向我在我热重启应用程序后。 以前它运行良好,但现在我不知道我的代码有什么问题,如果您能指出我的错误,那将对我大有帮助。 提前致谢
main.dart
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:provider/provider.dart';
import './providers/user_provider.dart';
import './screens/tab_bar_screen.dart';
import './screens/auth/auth_tab_bar_screen.dart';
import './screens/login_screen.dart';
import './screens/auth/admin/edit_project_screen.dart';
import './screens/auth/admin/register_user.dart';
import './screens/auth/project_detail_screen.dart';
import './providers/auth.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
Provider<Auth>(
create: (_) => Auth(FirebaseAuth.instance),
),
StreamProvider(
create: (context) =>
Provider.of<Auth>(context, listen: false).authStateChanges,
),
],
child: MaterialApp(
theme: ThemeData(
primaryColor: Colors.blue,
backgroundColor: Colors.blue,
accentColor: Colors.blueAccent,
brightness: Brightness.light,
accentColorBrightness: Brightness.light,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
debugShowCheckedModeBanner: false,
home: AuthenticationWrapper(),
routes: {
LoginScreen.routeName: (ctx) => LoginScreen(),
TabBarScreen.routeName: (ctx) => TabBarScreen(),
AuthTabBarScreen.routeName: (ctx) => AuthTabBarScreen(),
EditProjectScreen.routeName: (ctx) => EditProjectScreen(),
RegisterUserScreen.routeName: (ctx) => RegisterUserScreen(),
ProjectDetailScreen.routeName: (ctx) => ProjectDetailScreen(),
},
),
);
}
}
class AuthenticationWrapper extends StatelessWidget {
@override
Widget build(BuildContext context) {
final _firebaseUser = context.watch<User>();
if (_firebaseUser != null) {
return AuthTabBarScreen();
} else {
return TabBarScreen();
}
}
}
auth.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class Auth {
final FirebaseAuth _firebaseAuth;
Auth(this._firebaseAuth);
final databaseReference = FirebaseFirestore.instance;
Stream<User> get authStateChanges => _firebaseAuth.authStateChanges();
//Get Current User UID
Future<String> userUid() async {
return _firebaseAuth.currentUser.uid;
}
//Get Current User
Future<void> getCurrentUser() async {
return _firebaseAuth.currentUser;
}
Future<String> login(
String email,
String password,
) async {
try {
await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password);
return 'Signed in';
} on FirebaseAuthException catch (error) {
print(error.message);
return error.message;
}
}
Future<void> signUp(
String email,
String password,
String firstName,
String lastName,
bool isAdmin,
) async {
try {
// Create a new user
final currentUser = await _firebaseAuth.createUserWithEmailAndPassword(
email: email, password: password);
// Update user
await databaseReference
.collection("users")
.doc(currentUser.user.uid)
.set({
'firstName': firstName,
'lastName': lastName,
'email': currentUser.user.email,
'isAdmin': isAdmin,
});
} on FirebaseAuthException catch (error) {
return error.message;
}
}
Future<void> logout() async {
await _firebaseAuth.signOut();
}
}
login_screen.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/auth.dart';
class LoginScreen extends StatefulWidget {
static const routeName = '/login';
@override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final _passwordFocusNode = FocusNode();
final _passwordController = TextEditingController();
var _isLoading = false;
final _formKey = GlobalKey<FormState>();
Map<String, String> _authData = {
'email': '',
'password': '',
};
void _showErrorDialogBox(String message) async {
return showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: Text('An error occurred'),
content: Text(message),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.of(ctx).pop();
},
child: Text('Okay'),
),
],
),
);
}
@override
void dispose() {
_passwordFocusNode.dispose();
_passwordController.dispose();
super.dispose();
}
Future<void> _submit() async {
if (!_formKey.currentState.validate()) {
// Invalid!
return;
}
_formKey.currentState.save();
setState(() {
_isLoading = true;
});
try {
await Provider.of<Auth>(context, listen: false).login(
_authData['email'],
_authData['password'],
);
} on FirebaseAuthException catch (error) {
return error.message;
} catch (error) {
const errorMessage = 'Authentication failed, please try again later.';
_showErrorDialogBox(errorMessage);
} finally {
setState(() {
_isLoading = false;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Login'),
centerTitle: true,
),
body: Padding(
padding: const EdgeInsets.all(25),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
padding: EdgeInsets.only(top: 30, bottom: 30),
child: Image.asset('assets/images/logo.png'),
),
TextFormField(
decoration: InputDecoration(
labelText: 'E-Mail',
border: OutlineInputBorder(
borderSide:
BorderSide(color: Theme.of(context).primaryColor),
),
hintText: 'Type your email address',
hintStyle: TextStyle(
fontSize: 12,
),
),
keyboardType: TextInputType.emailAddress,
textInputAction: TextInputAction.next,
focusNode: _passwordFocusNode,
validator: (value) {
Pattern pattern =
r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
RegExp regex = new RegExp(pattern);
if (!regex.hasMatch(value))
return 'Enter a Valid Email';
else
return null;
},
onSaved: (value) {
_authData['email'] = value;
},
),
SizedBox(
height: 35,
),
TextFormField(
decoration: InputDecoration(
labelText: 'Password',
border: OutlineInputBorder(
borderSide:
BorderSide(color: Theme.of(context).primaryColor),
),
hintText: 'Type your password',
hintStyle: TextStyle(
fontSize: 12,
),
),
obscureText: true,
textInputAction: TextInputAction.done,
//controller: _passwordController,
validator: (value) {
if (value.isEmpty || value.length <= 5) {
return 'Password is too short!';
}
return null;
},
onSaved: (value) {
_authData['password'] = value;
},
),
SizedBox(
height: 35,
),
if (_isLoading)
CircularProgressIndicator()
else
RaisedButton(
color: Theme.of(context).primaryColor,
onPressed: _submit,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
child: Text(
'LOGIN',
style: TextStyle(
color: Colors.white,
),
),
),
],
),
),
),
),
);
}
}
答案 0 :(得分:1)
好吧,伙计们,我发现了问题所在,我在问题上发布的代码确实是正确的,问题在于我退出的方式
之前的代码:
// EF core test
[Test] // failed
public void Test1()
{
var options = new DbContextOptionsBuilder<ConsoleApp1.Context>()
.UseInMemoryDatabase(databaseName: "Data")
.ConfigureWarnings(x => x.Ignore(InMemoryEventId.TransactionIgnoredWarning))
.Options;
var context = new ConsoleApp1.Context(options);
context.Books.Add(new ConsoleApp1.Book { Id = -1 });
context.Books.Add(new ConsoleApp1.Book { Id = 0 });
context.Books.Add(new ConsoleApp1.Book { Id = -1 });
Assert.Pass();
}
// EF 6 test
[Test] // passed
public void Test2()
{
var context = new ConsoleApp2.Context();
context.Books.Add(new ConsoleApp2.Book { Id = -1 });
context.Books.Add(new ConsoleApp2.Book { Id = 0 });
context.Books.Add(new ConsoleApp2.Book { Id = -1 });
Assert.Pass();
}
固定代码:
ListTile(
leading: Icon(Icons.logout),
title: Text('Logout'),
onTap: () {
Navigator.of(context).pop();
Navigator.of(context)
.pushReplacementNamed(TabBarScreen.routeName);
Provider.of<Auth>(context, listen: false).logout();
},
)
这是因为firebase已经处理了ListTile(
leading: Icon(Icons.logout),
title: Text('Logout'),
onTap: () {
Provider.of<Auth>(context, listen: false).logout();
},
)
和pop()
到push()
(我在main.dart中给出的),当我手动尝试时出现了冲突到 homepage()
并替换页面并将用户重定向到 pop()
。
希望这是一个足够好的解释。