#flutter #riverpod
Вопрос:
Я пытаюсь использовать Navigator 2.0 и Riverpod для управления состоянием.
В моем классе состояния ( AppStateChangeNotifier
) у меня есть signIn()
метод и signOut()
метод.
Поток выглядит следующим образом: Экран входа в систему -gt; Загрузка -gt;gt; Главная
Домашний виджет-это просто кнопка, которая вызывает signOut()
метод AppStateChangeNotifier
. В нем также есть панель приложений с выдвижным ящиком. Внутри ящика у меня есть точно такая же кнопка, как на домашней странице, но эта кнопка неправильно возвращает приложение на экран входа в систему, оно просто закрывает ящик.
При использовании кнопки ящика я знаю, что приложение действительно вызывает build()
метод AppRouterDelegate
, но страницы обновляются не так, как ожидалось.
Может кто-нибудь, пожалуйста, объяснить, почему происходит такое поведение? Я не уверен, что я упускаю/неправильно понимаю.
Точка входа:
void main() async { runApp(const ProviderScope(child: App())); }
Класс управления состоянием приложения:
class AppStateChangeNotifier extends ChangeNotifier { bool _isSignedIn = false; bool get isSignedIn =gt; _isSignedIn; bool _isLoading = false; bool get isLoading =gt; _isLoading; Futurelt;voidgt; signIn() async { _isLoading = true; notifyListeners(); // simulate login operation await Future.delayed(const Duration(seconds: 2)); _isSignedIn = true; _isLoading = false; notifyListeners(); } Futurelt;voidgt; signOut() async { _isSignedIn = false; notifyListeners(); } } // used to manipulate state in the app from widgets in the tree final appStateChangeNotifier = ChangeNotifierProvider((ref) =gt; AppStateChangeNotifier());
Делегат маршрутизатора; build()
метод не обновляется должным образом при signOut()
вызове с Drawer
помощью кнопки.
class AppRouterDelegate extends RouterDelegatelt;Objectgt; with ChangeNotifier, PopNavigatorRouterDelegateMixinlt;Objectgt; { final GlobalKeylt;NavigatorStategt; _navigatorKey; final ProviderRefBase _ref; AppRouterDelegate(this._ref) : _navigatorKey = GlobalKeylt;NavigatorStategt;() { // subscribe to notifications _ref.read(appStateChangeNotifier).addListener(notifyListeners); } // calls signOut() Widget buildSignOutWidget() { return Center( child: TextButton( onPressed: () async { await _ref.read(appStateChangeNotifier).signOut(); }, child: const Text("Sign-Out"), ), ); } @override Widget build(BuildContext context) { log("is signed in? ${_ref.read(appStateChangeNotifier).isSignedIn}"); return Navigator( pages: [ MaterialPage( key: const ValueKey("in"), child: Scaffold( body: Center( child: TextButton( onPressed: () async { await _ref.read(appStateChangeNotifier).signIn(); }, child: const Text("Sign-In"), ), ), ), ), if (_ref.read(appStateChangeNotifier).isSignedIn) MaterialPage( key: const ValueKey("out"), child: Scaffold( appBar: AppBar(), drawer: Drawer( child: buildSignOutWidget(), ), body: buildSignOutWidget(), ), ), if (_ref.read(appStateChangeNotifier).isLoading) const MaterialPage( key: ValueKey("load"), child: Scaffold( body: Center( child: CircularProgressIndicator(), ), ), ), ], onPopPage: (route, result) =gt; route.didPop(result), ); } @override GlobalKeylt;NavigatorStategt;? get navigatorKey =gt; _navigatorKey; @override Futurelt;voidgt; setNewRoutePath(Object configuration) =gt; SynchronousFuture(null); }
Application widget:
// pass in a ProviderBaseRef to the AppRouterDelegate final appRouterDelegateProvider = Provider((ref) =gt; AppRouterDelegate(ref)); class App extends ConsumerWidget { const App({Key? key}) : super(key: key); @override Widget build(BuildContext context, WidgetRef ref) { return MaterialApp( home: Router(routerDelegate: ref.read(appRouterDelegateProvider)), ); } }