StateNotifierProvider не сохраняет состояние между перезапусками приложения

Использование flutter_riverpod: ^0.12.4 и тестирование в эмуляторе Android, а также на физическом устройстве.

Что я делаю не так, что значение экрана входа не сохраняется в StateNotifierProvider после перезапуска приложения?

По умолчанию для accountSetupProvider используется вводный экран. После нажатия кнопки onPressed на начальном экране отображается экран входа в систему, и он правильно запускает перестройку для отображения экрана входа в систему.

However, after a flutter hot restart or opening/closing the app, the Intro Screen, rather than the Sign In screen displays. Shouldn't the state, which now is set to the Sign In screen after clicking onPressed in the Intro Screen persist between restarts and cause the Intro Screen to be skipped and the Sign In screen to display?

As you can see below main.dart has an initial AppRoutes.root route. In app_router.dart, this "root" screen opens root_screen.dart, which is a ConsumerWidget that is watch(ing) my StateNotifierProvider called "accountSetupProvider" in account_setup_provider.dart.

main.dart

      Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  runApp(
    ProviderScope(
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: AppRoutes.root,
      onGenerateRoute: (settings) => AppRouter.onGenerateRoute(settings),
    );
  }
}

app_router.dart

      class AppRoutes {
  static const String root = RootScreen.id;
  static const String intro = IntroScreen.id;
  static const String signIn = SignInScreen.id;
}

class AppRouter {
  static Route<dynamic> onGenerateRoute(RouteSettings settings) {
    final _args = settings.arguments;

    switch (settings.name) {
      case AppRoutes.root:
        return MaterialPageRoute<dynamic>(
          builder: (_) => RootScreen(),
          settings: settings,
        );
      case AppRoutes.intro:
        return MaterialPageRoute<dynamic>(
          builder: (_) => IntroScreen(),
          settings: settings,
        );
      case AppRoutes.signIn:
        return MaterialPageRoute<dynamic>(
          builder: (_) => SignInScreen(),
          settings: settings,
        );
    }
  }
}

root_screen.dart

      class RootScreen extends ConsumerWidget {
  const RootScreen({Key key}) : super(key: key);
  static const String id = 'root_screen';

  @override
  Widget build(BuildContext context, ScopedReader watch) {
    final screen = watch(accountSetupProvider.state);

    if (screen == AppRoutes.signIn) {
      return SignInScreen();
    } else if (screen == AppRoutes.intro) {
      return IntroScreen();
    }
  }
}

intro_screen.dart (only including the onPressed portion of intro screen, which I'm expecting to set the state to the new screen, even after a flutter hot restart or app restart.)

      onPressed: () {
  context
    .read(accountSetupProvider) // see accountSetupProvider StateNotifierProvider below.
    .setScreen(AppRoutes.signIn);
},

account_setup_provider.dart (inits to the AppRoutes.intro screen.)

      class AccountSetupNotifier extends StateNotifier<String> {
  AccountSetupNotifier() : super(AppRoutes.intro);

  void setScreen(String screen) {
    state = screen;
  }
}

final accountSetupProvider = StateNotifierProvider<AccountSetupNotifier>((ref) {
  return AccountSetupNotifier();
});

1 ответ

Даже не глядя на ваш код и глядя только на вашу тему, меня это совсем не удивляет. «Горячий перезапуск» сбрасывает все переменные. Как могло быть хоть какое-то государство? Вы вместо этого ищете "Hot Reload"?

Другие вопросы по тегам