#flutter #dart #firebase-authentication
# #flutter #dart #firebase-аутентификация
Вопрос:
Я пытаюсь перейти на домашнюю страницу после входа в систему, это работает, я следовал этому одному руководству:
https://www.youtube.com/watch?v=oJ5Vrya3wCQamp;t=307s
Но моя проблема в том, что когда я захожу на кнопку регистрации> зарегистрировать пользователя, и это приводит меня прямо на страницу входа, но когда я заполняю формы входа и вхожу в систему, ничего не происходит, я должен выполнить «горячий перезапуск», чтобы увидеть свою домашнюю страницу, это как если бы какой-то виджет сделал не перестраивать заново. Итак, я должен сделать какой-нибудь лучший чистый способ сделать это statemanagement?
Главная:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:plantsapp/screens/login_page.dart';
import 'package:plantsapp/screens/plant_screen.dart';
import 'package:plantsapp/screens/register_page.dart';
import 'package:plantsapp/screens/shop_scree_page.dart';
import 'package:plantsapp/services/authentication_service.dart';
import 'package:provider/provider.dart';
void 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: [
ChangeNotifierProvider<AuthenticationService>(
create: (_) => AuthenticationService(FirebaseAuth.instance),
),
StreamProvider(create: (context) => context.read<AuthenticationService>().authStateChanges)
],
child: MaterialApp(
title: 'Flutter Plant Shop UI',
debugShowCheckedModeBanner: false,
home: AuthenticationWrapper(),
routes: {
'registerpage': (context) => RegisterPage(),
'loginpage': (context) => LoginPage(),
'homepage': (context) => PlantScreen(),
},
//theme: ThemeData.dark(),
),
);
}
}
// ignore: must_be_immutable
class AuthenticationWrapper extends StatelessWidget with ChangeNotifier{
@override
Widget build(BuildContext context) {
final firebaseuser = context.watch<User>();
notifyListeners();
if(firebaseuser != null) {
notifyListeners();
return ShopScreen();
} else {
notifyListeners();
return LoginPage();
}
}
}
Служба аутентификации:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart';
class AuthenticationService with ChangeNotifier{
final FirebaseAuth _firebaseAuth;
AuthenticationService(this._firebaseAuth);
Stream<User> get authStateChanges => _firebaseAuth.authStateChanges();
Future<String> signIn({String email, String password}) async {
try {
await _firebaseAuth.signInWithEmailAndPassword(email: email, password: password);
notifyListeners();
return "Signed in";
} on FirebaseAuthException catch (e) {
print(e);
return e.message;
}
}
Future<String> signUp({String email, String password, BuildContext context}) async{
try {
await _firebaseAuth.createUserWithEmailAndPassword(email: email, password: password);
print('USUARIO REGISTRADO');
Navigator.pushReplacementNamed(context, 'loginpage');
return "Signed Up";
} on FirebaseAuthException catch (e) {
print(e.message);
return e.message;
}
}
Future<void> signOut() async{
await _firebaseAuth.signOut();
notifyListeners();
}
}
Страница входа:
import 'package:flutter/material.dart';
import 'package:plantsapp/services/authentication_service.dart';
import 'package:provider/provider.dart';
class LoginPage extends StatefulWidget{
@override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage>{
final TextEditingController emailController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 20, vertical: 80),
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 80),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Login',
style: TextStyle(fontSize: 20),
),
_emailForm(),
_passwordForm(),
_button(),
_buttonRegister(),
],
),
),
),
);
}
Widget _emailForm() {
return TextField(
controller: emailController,
decoration: InputDecoration(hintText: ('Email')),
);
}
Widget _passwordForm() {
return TextField(
controller: passwordController,
decoration: InputDecoration(hintText: ('Password')),
);
}
Widget _button() {
return RaisedButton(
child: Text('Login'),
onPressed: () {
Provider.of<AuthenticationService>(context, listen: false).signIn(
email: emailController.text.trim(),
password: passwordController.text.trim());
},
);
}
_buttonRegister() {
return RaisedButton(
child: Text('Registrarse'),
onPressed: () {
Navigator.pushReplacementNamed(context, 'registerpage');
},
);
}
}
Страница регистрации:
import 'package:flutter/material.dart';
import 'package:plantsapp/services/authentication_service.dart';
import 'package:provider/provider.dart';
class RegisterPage extends StatefulWidget {
RegisterPage({Key key}) : super(key: key);
@override
_RegisterPageState createState() => _RegisterPageState();
}
class _RegisterPageState extends State<RegisterPage> {
final TextEditingController emailController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 20, vertical: 80),
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 80),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Registrarse',
style: TextStyle(fontSize: 30),
),
_emailForm(),
_passwordForm(),
_button(),
],
),
),
),
);
}
Widget _emailForm() {
return TextField(
controller: emailController,
decoration: InputDecoration(hintText: ('Email')),
);
}
Widget _passwordForm() {
return TextField(
controller: passwordController,
decoration: InputDecoration(hintText: ('Password')),
);
}
Widget _button() {
return RaisedButton(
child: Text('Registrarse'),
onPressed: () {
Provider.of<AuthenticationService>(context, listen: false).signUp(
email: emailController.text.trim(),
password: passwordController.text.trim(),
context: context);
},
);
}
}
Ответ №1:
В принципе, я бы сказал, что использование пакета поставщика в этом простейшем сценарии на самом деле не требуется. Обработка состояния аутентификации с помощью Firebase может быть легко достигнута с StreamBuilder
помощью и FirebaseAuth.instance.authStateChanges()
. Поэтому вместо того, чтобы нажимать страницы с помощью navigator и вызывать notifyListeners(), просто создайте StreamBuilder, который перестраивается при изменении состояния аутентификации (пакет firebase auth обрабатывает простейшее управление состоянием для вас, предоставляя вам удобный поток пользовательских объектов)
StreamBuilder<User>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (snapshot.data == null) return LoginScreen();
return YourScreenForSignedUsersScreen();
})
Комментарии:
1. я только что отключил класс «AuthenticationWrapper» в основном, и я добавил метод StreamBuilder в «home:», и он тот же, ДОЛЖЕН использовать горячую перезагрузку или горячий перезапуск, чтобы увидеть домашнюю страницу, это происходит ТОЛЬКО ТОГДА, КОГДА я захожу на registerpage, регистрирую пользователя, возвращаюсь к логину, и попробуйте войти в систему с этим пользователем, я нажимаю login и ничего, мне нужно выполнить горячую перезагрузку или горячую перезагрузку, чтобы он показал мне домашнюю страницу (ShopScreen () в данном случае).
2. Когда вы регистрируете нового пользователя, он автоматически входит в систему, так что вам не нужно снова запрашивать у пользователя логин (или, как я заключаю из вашего сообщения, вы, возможно, даже не можете этого сделать).
3. Попробуйте запустить свое приложение, не нажимая на экран входа в систему после регистрации (раньше этого не замечал). Это определенно может вызвать вашу проблему
4. Я удаляю нажатие для входа в систему при регистрации, но ничего не меняется, приложение остается на экране регистрации, я должен выполнить горячий перезапуск, чтобы показать мне домашнюю страницу сейчас .. я пробую что-то, пока публикую это, но ничего не работает.. должен ли я принудительно переходить на домашнюю страницу после регистрации? потому что StreamBuilder, похоже, не работает после регистрации пользователя
5. я хочу добавить следующее: после добавления принудительного навигатора замените имя на «домашнюю страницу» после регистрации, если я нажму кнопку «назад», она вернется на другую домашнюю страницу, а затем выйдите из приложения, например, теперь оно открывает 2 домашние страницы, но когда я не принудительно это сделал, виджет не перестроилсядля себя я должен запустить «горячий перезапуск», чтобы увидеть домашнюю страницу без принудительного использования навигатора..
Ответ №2:
я нашел проблему и хочу поделиться ею со всеми. Проблема заключалась в навигаторе, вы должны поддерживать поток, мое приложение запускается на странице входа, поэтому я использую навигатор для перехода на страницу регистрации, поэтому я запускаю приложение на странице регистрации без использования какого-либо навигатора между ними и тестирую его, и оно автоматически отправляет меня на домашнюю страницу.