Невозможно перейти на домашнюю страницу после регистрации в firebase Flutter

#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:

я нашел проблему и хочу поделиться ею со всеми. Проблема заключалась в навигаторе, вы должны поддерживать поток, мое приложение запускается на странице входа, поэтому я использую навигатор для перехода на страницу регистрации, поэтому я запускаю приложение на странице регистрации без использования какого-либо навигатора между ними и тестирую его, и оно автоматически отправляет меня на домашнюю страницу.