У меня есть приложение, которое для упрощения имеет два экрана. Основной из них называется так:
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
.
Но я не знаю, это не кажется мне хорошей практикой. Я новичок во Флаттере, но не станет ли это проблемой, если у меня будет несколько экранов друг над другом с одновременной проверкой нескольких потребителей? Разве он не начнет открывать кучу экранов входа в систему для каждого уже открытого экрана?