Flutter Auth Provider на нескольких экранах - PullRequest
0 голосов
/ 09 ноября 2019

У меня есть приложение, которое для упрощения имеет два экрана. Основной из них называется так:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {

    return ChangeNotifierProvider.value(
      value: Auth(),
      child: MaterialApp(

        title: 'MyApp',
        theme: ThemeData(
        home: Consumer<Auth>(
          builder: (context, auth, _) {

            return auth.isAuthenticated
                ? NavigationHomeScreen()
                : FutureBuilder(
                    future: auth.verifyAuthentication,
                    builder: (context, authResultSnapshot) =>
                        authResultSnapshot.connectionState ==
                                ConnectionState.waiting
                            ? SplashScreen()
                            : LoginScreen(),
                  );
          },
        ),
        routes: {
          Screen1.routeName: (ctx) => Screen1(),
          Screen2.routeName: (ctx) => Screen2(),
        });
...

Основным моментом здесь является проверка подлинности. Поставщик аутентификации используется во всем приложении. Так в чем проблема?

У меня есть ящик приложений, который используется на большинстве экранов (например, Screen1 и Screen2), включая, конечно, NavigationHomeScreen.

. Проблема в том, что у меня естьauth.logout() метод, который по существу очищает поле token, которое является ключом для сохранения пользователя в системе, это auth.dart:

class Auth with ChangeNotifier {
  String token;
  bool get isAuthenticated => token != null;

  Future<void> get verifyAuthentication async {
    final prefs = await SharedPreferences.getInstance();

    if (prefs.getString('token') != null) {
      token = prefs.getString('token');
      notifyListeners();
    }

    return token != null;
  }

  Future<void> logout() async {
    token = null;

    final prefs = await SharedPreferences.getInstance();

    prefs.remove('token');

    notifyListeners();
  }
  ...
}

Итак, когда я нажимаю auth.logout, это меняетAuth провайдера и NotifyListeners, у меня там Consumer<Auth>, который обновляется, а затем появляется LoginScreen.

Это прекрасно работает, когда я вызываю auth.logout из NavigationHomeScreen (это называется в моем Consumer там). Но когда я открываю новый экран с тем же ящиком, и я нажимаю auth.logout, приложение не перестраивается из-за изменений. И затем я получаю кучу ошибок, связанных с попытками доступа к информации внутри Auth провайдера, который сейчас null.

Мой вопрос: я что-то неправильно структурирую, чтобы это произошло, илиэто стандартное поведение?

Подход, который я собираюсь использовать, заключается в создании ParentWidget для всех моих экранов, в котором будет Consumer<Auth>, и который будет проверять, аутентифицирован ли пользователь. Если пользователь аутентифицирован, он покажет вызываемый экран, если нет, он вместо этого загрузит LoginScreen.

Но я не знаю, это не кажется мне хорошей практикой. Я новичок во Флаттере, но не станет ли это проблемой, если у меня будет несколько экранов друг над другом с одновременной проверкой нескольких потребителей? Разве он не начнет открывать кучу экранов входа в систему для каждого уже открытого экрана?

...