Провайдер не уведомляется, когда пользователи регистрируются - PullRequest
0 голосов
/ 14 июля 2020

Контекст

Я пытаюсь создать приложение, используя Flutter , которое требует от пользователей регистрации и / или входа . Используя провайдера, я мог при каждом запуске приложения определять, был ли пользователь уже авторизован или нет, показывая соответственно MainScreen или SignInScreen, как вы можете видеть из приведенного ниже кода.

void main() {
  runApp(Stuff());
}

class Stuff extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        StreamProvider<FirebaseUser>.value(value: AuthService().onAuthChanged),
      ],
      child: Consumer<FirebaseUser>(builder: (context, user, _) {
        return MaterialApp(
          title: 'Stuff',
          home:  user != null ? MainScreen() : SignInScreen(),
          routes: {
            '/main_screen' : (context) => MainScreen(),
            '/signup_screen': (context) => SignUpScreen(),
            '/signin_screen': (context) => SignInScreen(),
          },
        );
      }),
    );
  }
}

, где AuthService на данный момент выглядит следующим образом:

class AuthService{
  final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;

  @override
  Stream<FirebaseUser> get onAuthChanged => _firebaseAuth.onAuthStateChanged;
}

Если пользователь не вошел в систему, то отображается SignInScreen, а после процесса входа StreamProvider уведомляется правильно, и свойство home обновлений MaterialApp автоматически показывает MainScreen.

Проблема

Когда пользователи попадают в SignInScreen, у них есть выбор: войдите в систему или перейдите к другому SignUpScreen на зарегистрируйтесь ( экран приложения ), например:

GestureDetector(
    child: Text('Sign Up.'),
     onTap: () {
       Navigator.pushReplacementNamed(context, '/signup_screen');
     },
),

Если они выберут для входа, когда они будут выполнены, home будет правильно обновлен и MainScreen отображается, как я сказал выше. Но если они решат зарегистрироваться, , когда они закончили, ничего не происходит. Все слушатели уведомляются, но StreamProvider не получает это уведомление. Единственная причина, по которой я могу придумать такое поведение, заключается в том, что SignUpScreen выходит за рамки провайдера, но дерево виджетов, похоже, предполагает, что это так.

Дерево виджетов

Возможно, проблема в pushReplacementNamed?

PS: Я должен упомянуть, что GestureDetector является частью следующего метода, который я передаю свойству appBar объекта Scaffold.

  PreferredSize _buildAppBar() {
    return PreferredSize(
      preferredSize: Size.fromHeight(MediaQuery.of(context).size.height * 0.18),
      child: Container(
        constraints: BoxConstraints(
            maxHeight: MediaQuery.of(context).size.height * 0.18),
        padding: EdgeInsets.only(left: 45.0, right: 45.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.end,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text('Sign In'),
            SizedBox(
              height: 2.5,
            ),
            Row(
                children: [
                  Text('Have an account already?'),
                  SizedBox(
                    width: 4.0,
                  ),
                  GestureDetector(
                    child: Text('Sign In.'),
                    onTap: () {
                      Navigator.pushReplacementNamed(context, '/signin_screen');
                    },
                  ),
                ],
              ),
          ],
        ),
      ),
    );
  }

1 Ответ

0 голосов
/ 14 июля 2020

Я думаю, проблема здесь в том, что вы не уведомляете виджет Stuff, когда пользователь входит в систему. Вы можете обернуть его Streambuilder, чтобы прослушивать такие изменения AuthState.

class Stuff extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
       Provider<AuthService>(create: (_) => AuthService()),
      ],
      child: Consumer<AuthService>(builder: (context, auth, _) {
        return StreamBuilder<FirebaseUser>(ctx,AsyncSnapshot<FirebaseUser> snapshot)=> MaterialApp(
          title: 'Stuff',
          home: snapshot.data!= null &&  snapshot.data.user != null ? MainScreen() : SignInScreen(),
          routes: {
            '/main_screen' : (context) => MainScreen(),
            '/signup_screen': (context) => SignUpScreen(),
            '/signin_screen': (context) => SignInScreen(),
          },
        );
      }),
    );
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...