0

基本上我要做的是:当移动应用程序启动时,它会检查我的本地数据库中是否存在用户条目。检查时,现在有一个空的黄色屏幕,表示它正在加载/检查尚未完成。完成后,它应该根据用户数据显示一个屏幕。为此,我使用 Riverpod 包创建了一个 StateNotifierProvider。

class ChangeScreenNotifier extends StateNotifier<Screen> {
  ChangeScreenNotifier() : super(null);

  void changeTo(Screen screen) {
    state = screen;
  }
}

final initialScreenStateNotifierProvider = StateNotifierProvider<ChangeScreenNotifier>((ref) => ChangeScreenNotifier());

初始状态为 null,但也可以更改为我的屏幕枚举值(SignInScreen、EmailVerificationScreen 等)。

现在,当启动应用程序时,状态显然是空的,所以我显示的是黄屏。完成搜索后,状态从 null 更改为基于用户数据的值。因此,我之前创建了一个 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 是有效的。但是,当谈到为什么它立即变回 null 的问题时,这对我没有帮助。

4

1 回答 1

1

我自己找到了解决方案:基本上导致这种行为的原因是当我试图打电话时

context.read(<ProviderName>).doSomething();

构建方法还没有完成。

然后我要做的就是将方法包装在

WidgetsBinding.instance.addPostFrameCallback((_) => context.read(<ProviderName>).doSomething());
于 2020-12-15T13:32:07.030 回答