В основном я пытаюсь сделать следующее: Когда мобильное приложение запускается, оно проверяет, существует ли запись пользователя в моей локальной базе данных. При проверке пока пустой желтый экран, указывающий на то, что идет загрузка/проверка еще не сделана. Когда это будет сделано, он должен показать экран, основанный на данных пользователей. Для этого я создал StateNotifierProvider с пакетом Riverpod.
class ChangeScreenNotifier extends StateNotifier<Screen> {
ChangeScreenNotifier() : super(null);
void changeTo(Screen screen) {
state = screen;
}
}
final initialScreenStateNotifierProvider = StateNotifierProvider<ChangeScreenNotifier>((ref) => ChangeScreenNotifier());
Начальное состояние равно null, но его также можно изменить на значение перечисления моих экранов (SignInScreen, EmailVerificationScreen и т. д.).
Теперь при запуске приложения состояние, очевидно, равно нулю, поэтому я показываю желтый экран. После завершения поиска состояние меняется с нуля на значение, основанное на данных пользователей. Поэтому я создал оператор if раньше, который проверяет, является ли состояние нулевым, чтобы я знал, был ли уже начальный экран, который отображается после желтого экрана загрузки, или нет, и установил его.
final initialScreen = watch(initialScreenStateNotifierProvider.state);
return MaterialApp(
debugShowCheckedModeBanner: false,
supportedLocales: context.supportedLocales,
localizationsDelegates: context.localizationDelegates,
navigatorKey: Routes.sailor.navigatorKey,
onGenerateRoute: Routes.sailor.generator(),
home: StreamListener(
stream: localDatabase.streamLocalUser().map((localUser) => UserModel.fromLocalUser(localUser)),
onData: (UserModel userModel) {
print(initialScreen);
if (initialScreen == null) {
context.read(initialScreenStateNotifierProvider).changeTo(userModel == null ? Screen.OnboardingScreen : !userModel.isEmailVerified ? Screen.EmailVerificationScreen : Screen.HomeScreen);
}
print(initialScreen);
},
child: initialScreen == null ? Container(color: Colors.yellow) : initialScreen.screen
)
);
Но когда я вставляю пользователя и пользовательский поток снова запускается, он снова запускается внутри оператора if, что говорит мне, что состояние снова равно нулю. После того, как я несколько раз проверил состояние в разных местах, оно всегда говорит null.
Итак, теперь мой вопрос: почему он всегда равен нулю и не сохраняется на экране, который я прошел?
Примечание. После желтого экрана он показывает мне OnboardingScreen, как и должен, поэтому я знаю, что передача экрана в StateNotifier работает. Но это не помогает мне, когда дело доходит до вопроса, почему он сразу же возвращается к нулю.
Я нашел решение сам: В основном то, что, по-видимому, вызвало такое поведение, заключается в том, что когда я пытался вызвать
context.read(<ProviderName>).doSomething();
метод сборки еще не закончен.
Что мне нужно было сделать, так это обернуть метод внутри
WidgetsBinding.instance.addPostFrameCallback((_) => context.read(<ProviderName>).doSomething());
Вы всегда должны стараться избегать этих строк кода, но если нет другого пути, действуйте.
Это лучшая практика?