Flutter是使用单一代码库开发跨平台应用程序的绝佳工具。虽然Flutter很有用,但当您添加 Firebase 时它会变得更好。在本文中,我们将讨论如何使用 Firebase 在Flutter实现电子邮件/密码身份验证过程。
在本文中,我们将介绍以下flutter开发方面:
- 改进的小部件树。
- TextFormField 验证逻辑。
- 切换密码文本可见性。
- 处理 UI 中的身份验证错误。
- 具有加载状态的自定义提交按钮。
- UI 逻辑和 Firebase 身份验证逻辑,分开。
注意:在深入研究 Firebase 身份验证之前,请在Flutter应用程序中配置 Firebase。检查此链接以获取带有flutter的初始 firebase 设置。
项目预览
现在,让我们来看看实现。
第 1 步:安装和初始化 Firebase
安装:
在使用任何 Firebase 服务之前,您必须首先安装firebase_core 插件,该插件负责将您的应用程序连接到 Firebase。将插件添加到您的pubspec.yaml 文件中。此外,添加一些用于处理身份验证流程的支持插件。
项目/lib/pubspec.yaml
dependencies:
flutter:
sdk: flutter
firebase_core: "0.5.2"
firebase_auth: "^0.18.3"
provider: ^4.3.2+2
cloud_firestore: ^0.14.3
font_awesome_flutter: ^8.10.0
通过从项目根目录运行以下命令来安装插件:
$ flutter pub get
初始化 Firebase
要初始化 Firebase,请在 Firebase 类上调用.initializeApp() 方法,如下面的代码所述。这个方法是异步的并返回一个 Future,所以我们需要在显示我们的主应用程序之前确保它已经完成。更新main 的 main()方法。dart
项目/库/主。dart
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
第 2 步:Firebase 身份验证服务
认证流程:
/libservices/authentication_service.dart
创建一个新文件夹作为服务,并在其中创建一个新的dart文件作为authentication_service。 dart ,它将包含所有身份验证逻辑,以帮助我们分离 UI 逻辑。
authentication_service.dart
Dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_auth_example/models/user_model.dart';
class AuthenticationService {
final FirebaseAuth _firebaseAuth;
UserModel userModel = UserModel();
final userRef = Firestore.instance.collection("users");
AuthenticationService(this._firebaseAuth);
// managing the user state via stream.
// stream provides an immediate event of
// the user's current authentication state,
// and then provides subsequent events whenever
// the authentication state changes.
Stream get authStateChanges => _firebaseAuth.authStateChanges();
//1
Future signIn({String email, String password}) async {
try {
await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password);
return "Signed In";
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
return "No user found for that email.";
} else if (e.code == 'wrong-password') {
return "Wrong password provided for that user.";
} else {
return "Something Went Wrong.";
}
}
}
//2
Future signUp({String email, String password}) async {
try {
await _firebaseAuth.createUserWithEmailAndPassword(
email: email, password: password);
return "Signed Up";
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
return "The password provided is too weak.";
} else if (e.code == 'email-already-in-use') {
return "The account already exists for that email.";
} else {
return "Something Went Wrong.";
}
} catch (e) {
print(e);
}
}
//3
Future addUserToDB(
{String uid, String username, String email, DateTime timestamp}) async {
userModel = UserModel(
uid: uid, username: username, email: email, timestamp: timestamp);
await userRef.document(uid).setData(userModel.toMap(userModel));
}
//4
Future getUserFromDB({String uid}) async {
final DocumentSnapshot doc = await userRef.document(uid).get();
//print(doc.data());
return UserModel.fromMap(doc.data());
}
//5
Future signOut() async {
await _firebaseAuth.signOut();
}
}
Dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
class UserModel {
String email;
String uid;
String username;
DateTime timestamp;
UserModel({this.email, this.uid, this.username, this.timestamp});
Map toMap(UserModel user) {
var data = Map();
data["uid"] = user.uid;
data["username"] = user.username;
data["email"] = user.email;
data["timestamp"] = user.timestamp;
return data;
}
UserModel.fromMap(Map mapData) {
this.uid = mapData["uid"];
this.username = mapData["username"];
this.email = mapData["email"];
}
}
Dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_auth_example/pages/auth_screen_view.dart';
import 'package:flutter_auth_example/pages/home_page.dart';
import 'package:flutter_auth_example/services/authentication_service.dart';
import 'package:provider/provider.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
Provider(
create: (_) => AuthenticationService(FirebaseAuth.instance),
),
StreamProvider(
create: (context) =>
context.read().authStateChanges),
],
child: MaterialApp(
theme: ThemeData(
brightness: Brightness.dark,
primaryColor: Colors.green[400],
accentColor: Colors.deepOrange[200]),
home: AuthenticationWrapper(),
),
);
}
}
class AuthenticationWrapper extends StatelessWidget {
@override
Widget build(BuildContext context) {
final firebaseUser = context.watch();
if (firebaseUser != null) {
//If the user is successfully Logged-In.
return HomePage();
} else {
//If the user is not Logged-In.
return AuthScreenView();
}
}
}
Dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_auth_example/pages/login_page.dart';
import 'package:flutter_auth_example/pages/register_page.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
class AuthScreenView extends StatefulWidget {
@override
_AuthScreenViewState createState() => _AuthScreenViewState();
}
class _AuthScreenViewState extends State {
PageController pageController;
int pageIndex = 0;
@override
void initState() {
// TODO: implement initState
super.initState();
pageController = PageController();
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
pageController.dispose();
}
onPageChanged(int pageIndex) {
setState(() {
this.pageIndex = pageIndex;
});
}
onTap(int pageIndex) {
//pageController.jumpToPage(pageIndex);
pageController.animateToPage(pageIndex,
duration: Duration(milliseconds: 300), curve: Curves.easeInOut);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: PageView(
children: [
//when pageIndex == 0
LoginPage(),
//when pageIndex == 1
RegisterPage()
],
controller: pageController,
onPageChanged: onPageChanged,
),
bottomNavigationBar: CupertinoTabBar(
currentIndex: pageIndex,
onTap: onTap,
activeColor: Theme.of(context).primaryColor,
items: [
BottomNavigationBarItem(
title: Text("Log-In"),
icon: Icon(
FontAwesomeIcons.signInAlt,
)),
BottomNavigationBarItem(
title: Text("Register"),
icon: Icon(
FontAwesomeIcons.userPlus,
)),
],
),
);
}
}
Dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter_auth_example/services/authentication_service.dart';
import 'package:provider/provider.dart';
class RegisterPage extends StatefulWidget {
@override
_RegisterPageState createState() => _RegisterPageState();
}
class _RegisterPageState extends State {
//To Toggle Password Text Visibility.
bool _obscureText = true;
String _username, _email, _password;
//For the loading state.
bool _isSubmitting;
final _formKey = GlobalKey();
final _scaffoldKey = GlobalKey();
FirebaseAuth auth = FirebaseAuth.instance;
final DateTime timestamp = DateTime.now();
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(title: Text("GeeksForGeeks"), centerTitle: true),
body: Container(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Center(
child: SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
children: [
_showTitle(),
_showUsernameInput(),
_showEmailInput(),
_showPasswordInput(),
_showFormActions()
],
),
),
),
),
),
);
}
//1
_showTitle() {
return Text(
"Register",
style: TextStyle(fontSize: 72, fontWeight: FontWeight.bold),
);
}
//2
_showUsernameInput() {
return Padding(
padding: EdgeInsets.only(top: 20),
child: TextFormField(
onSaved: (val) => _username = val,
validator: (val) => val.length < 6 ? "Username is too short." : null,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: "Username",
hintText: "Enter Valid Username",
icon: Icon(
Icons.face,
color: Colors.grey,
)),
),
);
}
//3
_showEmailInput() {
return Padding(
padding: EdgeInsets.only(top: 20),
child: TextFormField(
onSaved: (val) => _email = val,
validator: (val) => !val.contains("@") ? "Invalid Email" : null,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: "Email",
hintText: "Enter Valid Email",
icon: Icon(
Icons.mail,
color: Colors.grey,
)),
),
);
}
//4
_showPasswordInput() {
return Padding(
padding: EdgeInsets.only(top: 20),
child: TextFormField(
onSaved: (val) => _password = val,
validator: (val) => val.length < 6 ? "Password Is Too Short" : null,
obscureText: _obscureText,
decoration: InputDecoration(
suffixIcon: GestureDetector(
onTap: () {
setState(() {
_obscureText = !_obscureText;
});
},
child:
Icon(_obscureText ? Icons.visibility_off : Icons.visibility),
),
border: OutlineInputBorder(),
labelText: "Password",
hintText: "Enter Valid Password",
icon: Icon(
Icons.lock,
color: Colors.grey,
)),
),
);
}
//5
_showFormActions() {
return Padding(
padding: EdgeInsets.only(top: 20),
child: Column(
children: [
_isSubmitting == true
? CircularProgressIndicator(
valueColor:
AlwaysStoppedAnimation(Theme.of(context).primaryColor),
)
: RaisedButton(
child: Text(
"Submit",
style: TextStyle(color: Colors.black, fontSize: 18),
),
elevation: 8.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10))),
color: Colors.orange,
onPressed: _submit),
],
),
);
}
//6
_submit() {
final _form = _formKey.currentState;
if (_form.validate()) {
_form.save();
//print("Email $_email, Password $_password, Username $_username");
_registerUser();
} else {
print("Form is Invalid");
}
}
//7
_registerUser() async {
setState(() {
_isSubmitting = true;
});
final logMessage = await context
.read()
.signUp(email: _email, password: _password);
logMessage == "Signed Up"
? _showSuccessSnack(logMessage)
: _showErrorSnack(logMessage);
print(logMessage);
if (logMessage == "Signed Up") {
createUserInFirestore();
} else {
setState(() {
_isSubmitting = false;
});
}
}
//When User "Signed Up", success snack will display.
_showSuccessSnack(String message) {
final snackbar = SnackBar(
backgroundColor: Colors.black,
content: Text(
"$message",
style: TextStyle(color: Colors.green),
),
);
_scaffoldKey.currentState.showSnackBar(snackbar);
_formKey.currentState.reset();
}
//When FirebaseAuth Catches error, error snack will display.
_showErrorSnack(String message) {
final snackbar = SnackBar(
backgroundColor: Colors.black,
content: Text(
"$message",
style: TextStyle(color: Colors.red),
),
);
_scaffoldKey.currentState.showSnackBar(snackbar);
}
createUserInFirestore() async {
context.read().addUserToDB(
uid: auth.currentUser.uid,
username: _username,
email: auth.currentUser.email,
timestamp: timestamp);
}
}
Dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter_auth_example/services/authentication_service.dart';
import 'package:provider/provider.dart';
class LoginPage extends StatefulWidget {
@override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State {
bool _obscureText = true;
String _email, _password;
bool _isSubmitting;
final _formKey = GlobalKey();
final _scaffoldKey = GlobalKey();
FirebaseAuth auth = FirebaseAuth.instance;
final DateTime timestamp = DateTime.now();
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
centerTitle: true,
title: Text("GeeksForGeeks"),
),
body: Container(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Center(
child: SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
children: [
_showTitle(),
_showEmailInput(),
_showPasswordInput(),
_showFormActions()
],
),
),
),
),
),
);
}
_showTitle() {
return Text(
"Login",
style: TextStyle(fontSize: 72, fontWeight: FontWeight.bold),
);
}
_showEmailInput() {
return Padding(
padding: EdgeInsets.only(top: 20),
child: TextFormField(
onSaved: (val) => _email = val,
validator: (val) => !val.contains("@") ? "Invalid Email" : null,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: "Email",
hintText: "Enter Valid Email",
icon: Icon(
Icons.mail,
color: Colors.grey,
)),
),
);
}
_showPasswordInput() {
return Padding(
padding: EdgeInsets.only(top: 20),
child: TextFormField(
onSaved: (val) => _password = val,
validator: (val) => val.length < 6 ? "Password Is Too Short" : null,
obscureText: _obscureText,
decoration: InputDecoration(
suffixIcon: GestureDetector(
onTap: () {
setState(() {
_obscureText = !_obscureText;
});
},
child:
Icon(_obscureText ? Icons.visibility_off : Icons.visibility),
),
border: OutlineInputBorder(),
labelText: "Password",
hintText: "Enter Valid Password",
icon: Icon(
Icons.lock,
color: Colors.grey,
)),
),
);
}
_showFormActions() {
return Padding(
padding: EdgeInsets.only(top: 20),
child: Column(
children: [
_isSubmitting == true
? CircularProgressIndicator(
valueColor:
AlwaysStoppedAnimation(Theme.of(context).primaryColor),
)
: RaisedButton(
child: Text(
"Submit",
style: TextStyle(color: Colors.black, fontSize: 18),
),
elevation: 8.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10))),
color: Colors.orange,
onPressed: _submit),
],
),
);
}
_submit() {
final _form = _formKey.currentState;
if (_form.validate()) {
_form.save();
//print("Email $_email, Password $_password");
_LoginUser();
} else {
print("Form is Invalid");
}
}
_LoginUser() async {
setState(() {
_isSubmitting = true;
});
final logMessage = await context
.read()
.signIn(email: _email, password: _password);
logMessage == "Signed In"
? _showSuccessSnack(logMessage)
: _showErrorSnack(logMessage);
//print("I am logMessage $logMessage");
if (logMessage == "Signed In") {
return;
} else {
setState(() {
_isSubmitting = false;
});
}
}
_showSuccessSnack(String message) async {
final snackbar = SnackBar(
backgroundColor: Colors.black,
content: Text(
"$message",
style: TextStyle(color: Colors.green),
),
);
_scaffoldKey.currentState.showSnackBar(snackbar);
_formKey.currentState.reset();
}
_showErrorSnack(String message) {
final snackbar = SnackBar(
backgroundColor: Colors.black,
content: Text(
"$message",
style: TextStyle(color: Colors.red),
),
);
_scaffoldKey.currentState.showSnackBar(snackbar);
setState(() {
_isSubmitting = false;
});
}
}
Dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter_auth_example/models/user_model.dart';
import 'package:flutter_auth_example/services/authentication_service.dart';
import 'package:provider/provider.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State {
FirebaseAuth auth = FirebaseAuth.instance;
final userRef = Firestore.instance.collection("users");
UserModel _currentUser;
String _uid;
String _username;
String _email;
@override
void initState() {
// TODO: implement initState
super.initState();
getCurrentUser();
}
getCurrentUser() async {
UserModel currentUser = await context
.read()
.getUserFromDB(uid: auth.currentUser.uid);
_currentUser = currentUser;
print("${_currentUser.username}");
setState(() {
_uid = _currentUser.uid;
_username = _currentUser.username;
_email = _currentUser.email;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("HomePage"),
centerTitle: true,
),
body: _currentUser == null
? Center(child: CircularProgressIndicator())
: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"uid is ${_uid} , email is ${_email}, name is ${_username}",
textAlign: TextAlign.center,
),
Center(
child: RaisedButton(
child: Text(
"Logout",
style: TextStyle(color: Colors.black, fontSize: 18),
),
elevation: 8.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10))),
color: Colors.orange,
onPressed: () {
context.read().signOut();
},
),
),
],
),
);
}
}
/libmodels/user_model.dart
Dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
class UserModel {
String email;
String uid;
String username;
DateTime timestamp;
UserModel({this.email, this.uid, this.username, this.timestamp});
Map toMap(UserModel user) {
var data = Map();
data["uid"] = user.uid;
data["username"] = user.username;
data["email"] = user.email;
data["timestamp"] = user.timestamp;
return data;
}
UserModel.fromMap(Map mapData) {
this.uid = mapData["uid"];
this.username = mapData["username"];
this.email = mapData["email"];
}
}
用户模型。 dart只是一个普通的旧Dart对象策略,用于将用户模型转换为 Map 并将其作为 Map 检索,就像它基本上是 JSON 对象一样。
身份验证服务。dart文件:
以下是 authentication_service 中使用的方法。dart文件:
1. 登录({字符串电子邮件,字符串密码})
- 此方法接受电子邮件和密码作为参数。
- 电子邮件和密码用于登录用户。
- 当用户“登录”时,它会返回一条适当的消息。
- 当FirebaseAuthException捕获错误时,它会返回适当的消息。
2.注册({字符串电子邮件,字符串密码})
- 此方法接受电子邮件和密码作为参数。
- 电子邮件和密码用于注册用户。
- 它返回当用户“签署了”相应的消息。
- 当FirebaseAuthException捕获错误时,它会返回适当的消息。
3. addUserToDB({String uid, String username, String email, DateTime timestamp})
- 此方法接受用户uid 、用户名、电子邮件和用户的当前时间戳( DateTime.now( ) )作为参数。
- 在Cloud Firestore 数据库中创建当前用户的新文档。 (请从您的 Firebase 项目控制台启用云Firestore )。文档名称应该是用户的uid 。
- 该方法只能在当前用户是新用户时触发,即初始点在我们的应用程序中注册的用户。
4. getUserFromDB({String uid})
- 此方法接受当前用户uid作为参数。
- 它将帮助我们从 Cloud Firestore数据库中获取当前用户的存储数据。
5.退出()
- 此方法仅用于从应用程序中注销用户。
步骤 4:检查身份验证状态
在我们的main中将AuthenticationService方法注册为 Provider 。dart文件。
项目/库/主。dart
Dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_auth_example/pages/auth_screen_view.dart';
import 'package:flutter_auth_example/pages/home_page.dart';
import 'package:flutter_auth_example/services/authentication_service.dart';
import 'package:provider/provider.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
Provider(
create: (_) => AuthenticationService(FirebaseAuth.instance),
),
StreamProvider(
create: (context) =>
context.read().authStateChanges),
],
child: MaterialApp(
theme: ThemeData(
brightness: Brightness.dark,
primaryColor: Colors.green[400],
accentColor: Colors.deepOrange[200]),
home: AuthenticationWrapper(),
),
);
}
}
class AuthenticationWrapper extends StatelessWidget {
@override
Widget build(BuildContext context) {
final firebaseUser = context.watch();
if (firebaseUser != null) {
//If the user is successfully Logged-In.
return HomePage();
} else {
//If the user is not Logged-In.
return AuthScreenView();
}
}
}
main的AuthenticationWrapper类。 dart,检查用户的状态。如果用户未登录,它将显示AuthScreenView() ,如果用户已登录,它将显示HomePage() 。
第 5 步:根据身份验证状态在 ScreenView 之间切换。
AuthScreenView():
/lib/pages/auth_screen_view.dart
AuthScreenView只是一个pageview ,它处理LoginPage()和RegisterPage()之间的切换。
auth_screen_view.dart
Dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_auth_example/pages/login_page.dart';
import 'package:flutter_auth_example/pages/register_page.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
class AuthScreenView extends StatefulWidget {
@override
_AuthScreenViewState createState() => _AuthScreenViewState();
}
class _AuthScreenViewState extends State {
PageController pageController;
int pageIndex = 0;
@override
void initState() {
// TODO: implement initState
super.initState();
pageController = PageController();
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
pageController.dispose();
}
onPageChanged(int pageIndex) {
setState(() {
this.pageIndex = pageIndex;
});
}
onTap(int pageIndex) {
//pageController.jumpToPage(pageIndex);
pageController.animateToPage(pageIndex,
duration: Duration(milliseconds: 300), curve: Curves.easeInOut);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: PageView(
children: [
//when pageIndex == 0
LoginPage(),
//when pageIndex == 1
RegisterPage()
],
controller: pageController,
onPageChanged: onPageChanged,
),
bottomNavigationBar: CupertinoTabBar(
currentIndex: pageIndex,
onTap: onTap,
activeColor: Theme.of(context).primaryColor,
items: [
BottomNavigationBarItem(
title: Text("Log-In"),
icon: Icon(
FontAwesomeIcons.signInAlt,
)),
BottomNavigationBarItem(
title: Text("Register"),
icon: Icon(
FontAwesomeIcons.userPlus,
)),
],
),
);
}
}
注册页面( ):
/lib/pages/register_page.dart
Dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter_auth_example/services/authentication_service.dart';
import 'package:provider/provider.dart';
class RegisterPage extends StatefulWidget {
@override
_RegisterPageState createState() => _RegisterPageState();
}
class _RegisterPageState extends State {
//To Toggle Password Text Visibility.
bool _obscureText = true;
String _username, _email, _password;
//For the loading state.
bool _isSubmitting;
final _formKey = GlobalKey();
final _scaffoldKey = GlobalKey();
FirebaseAuth auth = FirebaseAuth.instance;
final DateTime timestamp = DateTime.now();
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(title: Text("GeeksForGeeks"), centerTitle: true),
body: Container(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Center(
child: SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
children: [
_showTitle(),
_showUsernameInput(),
_showEmailInput(),
_showPasswordInput(),
_showFormActions()
],
),
),
),
),
),
);
}
//1
_showTitle() {
return Text(
"Register",
style: TextStyle(fontSize: 72, fontWeight: FontWeight.bold),
);
}
//2
_showUsernameInput() {
return Padding(
padding: EdgeInsets.only(top: 20),
child: TextFormField(
onSaved: (val) => _username = val,
validator: (val) => val.length < 6 ? "Username is too short." : null,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: "Username",
hintText: "Enter Valid Username",
icon: Icon(
Icons.face,
color: Colors.grey,
)),
),
);
}
//3
_showEmailInput() {
return Padding(
padding: EdgeInsets.only(top: 20),
child: TextFormField(
onSaved: (val) => _email = val,
validator: (val) => !val.contains("@") ? "Invalid Email" : null,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: "Email",
hintText: "Enter Valid Email",
icon: Icon(
Icons.mail,
color: Colors.grey,
)),
),
);
}
//4
_showPasswordInput() {
return Padding(
padding: EdgeInsets.only(top: 20),
child: TextFormField(
onSaved: (val) => _password = val,
validator: (val) => val.length < 6 ? "Password Is Too Short" : null,
obscureText: _obscureText,
decoration: InputDecoration(
suffixIcon: GestureDetector(
onTap: () {
setState(() {
_obscureText = !_obscureText;
});
},
child:
Icon(_obscureText ? Icons.visibility_off : Icons.visibility),
),
border: OutlineInputBorder(),
labelText: "Password",
hintText: "Enter Valid Password",
icon: Icon(
Icons.lock,
color: Colors.grey,
)),
),
);
}
//5
_showFormActions() {
return Padding(
padding: EdgeInsets.only(top: 20),
child: Column(
children: [
_isSubmitting == true
? CircularProgressIndicator(
valueColor:
AlwaysStoppedAnimation(Theme.of(context).primaryColor),
)
: RaisedButton(
child: Text(
"Submit",
style: TextStyle(color: Colors.black, fontSize: 18),
),
elevation: 8.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10))),
color: Colors.orange,
onPressed: _submit),
],
),
);
}
//6
_submit() {
final _form = _formKey.currentState;
if (_form.validate()) {
_form.save();
//print("Email $_email, Password $_password, Username $_username");
_registerUser();
} else {
print("Form is Invalid");
}
}
//7
_registerUser() async {
setState(() {
_isSubmitting = true;
});
final logMessage = await context
.read()
.signUp(email: _email, password: _password);
logMessage == "Signed Up"
? _showSuccessSnack(logMessage)
: _showErrorSnack(logMessage);
print(logMessage);
if (logMessage == "Signed Up") {
createUserInFirestore();
} else {
setState(() {
_isSubmitting = false;
});
}
}
//When User "Signed Up", success snack will display.
_showSuccessSnack(String message) {
final snackbar = SnackBar(
backgroundColor: Colors.black,
content: Text(
"$message",
style: TextStyle(color: Colors.green),
),
);
_scaffoldKey.currentState.showSnackBar(snackbar);
_formKey.currentState.reset();
}
//When FirebaseAuth Catches error, error snack will display.
_showErrorSnack(String message) {
final snackbar = SnackBar(
backgroundColor: Colors.black,
content: Text(
"$message",
style: TextStyle(color: Colors.red),
),
);
_scaffoldKey.currentState.showSnackBar(snackbar);
}
createUserInFirestore() async {
context.read().addUserToDB(
uid: auth.currentUser.uid,
username: _username,
email: auth.currentUser.email,
timestamp: timestamp);
}
}
输出:
登录页面( ):
LoginPage与RegisterPage完全相似,唯一的区别是 LoginPage 只有两个 TextFormField(用于电子邮件和密码)并且在提交时触发 signIn() authentication_service 的方法。dart
/lib /pages/login_page.dart
Dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter_auth_example/services/authentication_service.dart';
import 'package:provider/provider.dart';
class LoginPage extends StatefulWidget {
@override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State {
bool _obscureText = true;
String _email, _password;
bool _isSubmitting;
final _formKey = GlobalKey();
final _scaffoldKey = GlobalKey();
FirebaseAuth auth = FirebaseAuth.instance;
final DateTime timestamp = DateTime.now();
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
centerTitle: true,
title: Text("GeeksForGeeks"),
),
body: Container(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Center(
child: SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
children: [
_showTitle(),
_showEmailInput(),
_showPasswordInput(),
_showFormActions()
],
),
),
),
),
),
);
}
_showTitle() {
return Text(
"Login",
style: TextStyle(fontSize: 72, fontWeight: FontWeight.bold),
);
}
_showEmailInput() {
return Padding(
padding: EdgeInsets.only(top: 20),
child: TextFormField(
onSaved: (val) => _email = val,
validator: (val) => !val.contains("@") ? "Invalid Email" : null,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: "Email",
hintText: "Enter Valid Email",
icon: Icon(
Icons.mail,
color: Colors.grey,
)),
),
);
}
_showPasswordInput() {
return Padding(
padding: EdgeInsets.only(top: 20),
child: TextFormField(
onSaved: (val) => _password = val,
validator: (val) => val.length < 6 ? "Password Is Too Short" : null,
obscureText: _obscureText,
decoration: InputDecoration(
suffixIcon: GestureDetector(
onTap: () {
setState(() {
_obscureText = !_obscureText;
});
},
child:
Icon(_obscureText ? Icons.visibility_off : Icons.visibility),
),
border: OutlineInputBorder(),
labelText: "Password",
hintText: "Enter Valid Password",
icon: Icon(
Icons.lock,
color: Colors.grey,
)),
),
);
}
_showFormActions() {
return Padding(
padding: EdgeInsets.only(top: 20),
child: Column(
children: [
_isSubmitting == true
? CircularProgressIndicator(
valueColor:
AlwaysStoppedAnimation(Theme.of(context).primaryColor),
)
: RaisedButton(
child: Text(
"Submit",
style: TextStyle(color: Colors.black, fontSize: 18),
),
elevation: 8.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10))),
color: Colors.orange,
onPressed: _submit),
],
),
);
}
_submit() {
final _form = _formKey.currentState;
if (_form.validate()) {
_form.save();
//print("Email $_email, Password $_password");
_LoginUser();
} else {
print("Form is Invalid");
}
}
_LoginUser() async {
setState(() {
_isSubmitting = true;
});
final logMessage = await context
.read()
.signIn(email: _email, password: _password);
logMessage == "Signed In"
? _showSuccessSnack(logMessage)
: _showErrorSnack(logMessage);
//print("I am logMessage $logMessage");
if (logMessage == "Signed In") {
return;
} else {
setState(() {
_isSubmitting = false;
});
}
}
_showSuccessSnack(String message) async {
final snackbar = SnackBar(
backgroundColor: Colors.black,
content: Text(
"$message",
style: TextStyle(color: Colors.green),
),
);
_scaffoldKey.currentState.showSnackBar(snackbar);
_formKey.currentState.reset();
}
_showErrorSnack(String message) {
final snackbar = SnackBar(
backgroundColor: Colors.black,
content: Text(
"$message",
style: TextStyle(color: Colors.red),
),
);
_scaffoldKey.currentState.showSnackBar(snackbar);
setState(() {
_isSubmitting = false;
});
}
}
输出:
主页:
HomePage将在firebaseUser != null时显示,从main检查。dart
lib/pages/home_page.dart
Dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter_auth_example/models/user_model.dart';
import 'package:flutter_auth_example/services/authentication_service.dart';
import 'package:provider/provider.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State {
FirebaseAuth auth = FirebaseAuth.instance;
final userRef = Firestore.instance.collection("users");
UserModel _currentUser;
String _uid;
String _username;
String _email;
@override
void initState() {
// TODO: implement initState
super.initState();
getCurrentUser();
}
getCurrentUser() async {
UserModel currentUser = await context
.read()
.getUserFromDB(uid: auth.currentUser.uid);
_currentUser = currentUser;
print("${_currentUser.username}");
setState(() {
_uid = _currentUser.uid;
_username = _currentUser.username;
_email = _currentUser.email;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("HomePage"),
centerTitle: true,
),
body: _currentUser == null
? Center(child: CircularProgressIndicator())
: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"uid is ${_uid} , email is ${_email}, name is ${_username}",
textAlign: TextAlign.center,
),
Center(
child: RaisedButton(
child: Text(
"Logout",
style: TextStyle(color: Colors.black, fontSize: 18),
),
elevation: 8.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10))),
color: Colors.orange,
onPressed: () {
context.read().signOut();
},
),
),
],
),
);
}
}
输出: