Провайдер вход в систему выход из системы трепетание

Я пытаюсь создать простой поток аутентификации с помощью Provider. У меня три страницы:

  1. Страница авторизации
  2. Стартовая страница
  3. Главная страница

Поток этого приложения:

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

Вот моя настройка в коде:

main.dart

void main() {
  runApp(MultiProvider(providers: [
    ChangeNotifierProvider<StorageHelper>(create: (_) => StorageHelper()),
    ChangeNotifierProvider<AuthProvider>(create: (_) => AuthProvider()),
  ], child: MyApp()));
}

class MyApp extends StatelessWidget {
  Widget build(BuildContext context) {
    return Consumer<AuthProvider>(builder: (final BuildContext context,
        final AuthProvider authProvider, final Widget child) {
        print(authProvider.isAuthenticated); // this is false whenever I //click the logout from category(or other pushed pages) but the below ternary //operation is not executing
      return MaterialApp(
          title: 'My Poor App',
          debugShowCheckedModeBanner: false,
          theme: ThemeData(
            primaryColor: Color(0xff29c17e),
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          home: authProvider.isAuthenticated ? HomeScreen() : LoginScreen(),
          onGenerateRoute: Router.onGenerateRoute,
        );
    });
  }
}

LoginScreen.dart

class LoginScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final authProvider = Provider.of<AuthProvider>(context, listen: false);
    return Scaffold(
      body: Center(
          child: MaterialButton(
              onPressed: () async {
                await authProvider.emailLogin('[email protected]', 'pass');
              },
              child: Text('Login'))),
    );
  }
}

HomeScreen.dart

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final auth = Provider.of<AuthProvider>(context, listen: false);
    return Scaffold(
      body: Center(
        child: MaterialButton(
                elevation: 2,
                onPressed: () {
                  Navigator.push(
                      context,
                      MaterialPageRoute(
                          builder: (context) => CategoryScreen()));
                },
                child: Text('Reset')),
      ),
    );
  }
}

AuthProvider.dart

class AuthProvider extends ChangeNotifier {
  bool _isAuthenticated = false;

  bool get isAuthenticated => _isAuthenticated;

  set isAuthenticated(bool isAuth) {
    _isAuthenticated = isAuth;
    notifyListeners();
  }

  Future emailLogin(String email, String password) async {
    isAuthenticated = true;
  }

  Future logout() async {
    isAuthenticated = false;
  }
}

Если я выхожу с домашней страницы с помощью Provider.of<AuthProvider>(context).logout(), он работает нормально. Но если я push или pushReplacement выбираю новый маршрут и пытаюсь выйти из нового маршрута (просто скажем, что я перешел из дома на страницу категории и попытаюсь выйти оттуда), меня не перенаправят на LoginPage. Если я печатаю значение isAuthenticated, оно выводит false, но потребитель не слушает или, по крайней мере, не реагирует на изменение переменной.

Пожалуйста, не помечайте этот вопрос как повторяющийся, я искал много других похожих вопросов, и ни один из них не помог в моем случае.

Изменить: CategoryScreen.dart

class CategoryScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: RaisedButton(
          onPressed: () {
            final auth = Provider.of<AuthProvider>(context, listen: false);
            auth.logout();
            // print(auth.isAuthenticated);
          },
          child: Text('Category Logout'),
        ),
      ),
    );
  }
}

Дерево виджетов страницы первого входа

Дерево виджетов главной страницы

Дерево виджетов после navigator.pushAndRemoveUntil (CategoryScreen)


person Suraj Khanal    schedule 17.08.2020    source источник
comment
Думаю, проблема в вашем Navigator. При выходе из Category используйте Navigator.pushAndRemoveUntil или Navigator.pushNamedAndRemoveUntil после выхода из системы   -  person Alok    schedule 17.08.2020
comment
@Alok проверил это, и это не сработало.   -  person Suraj Khanal    schedule 17.08.2020
comment
Вы застреваете на той же странице, только когда пытаетесь выйти из CategoryPage?   -  person Alok    schedule 17.08.2020
comment
@ Алок. да, каждая вторая страница, которую я нажимаю с помощью навигатора и пытаюсь выйти оттуда, просто остается на месте. Потребитель вообще не реагирует. И я не получаю ошибок в консоли.   -  person Suraj Khanal    schedule 17.08.2020
comment
@Alok Я обновил фрагмент CategoryScreen. Должен ли я использовать там notifyListener? Я уже меняю значение isAuthenticated, используя сеттер, а сеттер использует notifyListner.   -  person Suraj Khanal    schedule 17.08.2020
comment
Используйте notifyListener() в logout() метод в AuthProvider   -  person Alok    schedule 17.08.2020
comment
@Alok По-прежнему не работает. Я напечатал значение внутри потребителя, и оно дает false всякий раз, когда я нажимаю на выход, но меня удивляет, почему оно не работает в этой логике.   -  person Suraj Khanal    schedule 17.08.2020
comment
Почему бы вам не сделать Navigator.pushAndRemoveUntil() после выхода из системы? Не удалось увидеть это в коде в CategoryScreen   -  person Alok    schedule 17.08.2020
comment
@Alok Если я правильно понимаю поставщика, я предположил, что потребитель должен отреагировать на это изменение и выполнить внутреннюю логику. Ваши предложения кажутся работающими, но проблема в том, что я перешел на страницу входа в систему, но после этого, если я нажму кнопку входа в систему, она перестанет работать.   -  person Suraj Khanal    schedule 17.08.2020
comment
Ознакомьтесь с ответом Сурадж. Надеюсь, у вас это сработает :) Дайте мне знать, иначе мы поищем другие изменения. Но я дал вам более широкую картину по этому поводу.   -  person Alok    schedule 17.08.2020


Ответы (1)


Думаю, ваша проблема в том, что вы не использовали Consumer для logout в своем home в MaterialApp. Просто посмотри, если это сработает для тебя

main.dart

// needs to listen to the changes, to make changes 
home: Consumer<AuthProvider>(
  builder: (context, authProvider, child){
     return authProvider.isAuthenticated ? HomeScreen() : LoginScreen();
  }
)

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

person Alok    schedule 17.08.2020
comment
Та же самая страница входа или домашняя страница под виджетом потребителя заменяется новой страницей, помещенной навигатором непосредственно под MaterialApp. Теперь я потерял потребительский виджет в дереве. - person Suraj Khanal; 17.08.2020
comment
Используйте своего потребителя для Home, а не для MaterialApp @SurajKhanal - person Alok; 17.08.2020
comment
Точно реализовано, как ваш ответ. - person Suraj Khanal; 17.08.2020