StateNotifierProvider 在应用程序重新启动之间不保持状态

Posted

技术标签:

【中文标题】StateNotifierProvider 在应用程序重新启动之间不保持状态【英文标题】:StateNotifierProvider not keeping state between app restarts 【发布时间】:2021-05-19 20:42:31 【问题描述】:

使用flutter_riverpod: ^0.12.4 并在安卓模拟器和物理设备上进行测试。

重新启动应用程序后,登录屏幕state 值没有保留在 StateNotifierProvider 中,我做错了什么?

accountSetupProvider 的state 默认为介绍屏幕。单击介绍屏幕的 onPressed 按钮后,state 将更新为登录屏幕,并正确触发重建以显示登录屏幕。

但是,在颤振热重启或打开/关闭应用程序后,会显示介绍屏幕,而不是登录屏幕。 state(在介绍屏幕中单击 onPressed 后现在设置为登录屏幕)不应该在重新启动之间持续存在并导致跳过介绍屏幕并显示登录屏幕吗?

正如您在下面看到的,main.dart 有一个初始 AppRoutes.root 路由。在app_router.dart 中,此“根”屏幕打开root_screen.dart,这是一个ConsumerWidget,即watch(ing) 我的StateNotifierProvider 在account_setup_provider.dart 中称为“accountSetupProvider”。

ma​​in.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(仅包括介绍屏幕的onPressed 部分,我希望将状态设置为新屏幕,即使在颤振热重启或应用重启后也是如此。)

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

account_setup_provider.dart(初始化到AppRoutes.intro 屏幕。)

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

  void setScreen(String screen) 
    state = screen;
  


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

【问题讨论】:

【参考方案1】:

甚至不看你的代码,只看你的主题行,这对我来说一点也不奇怪。 “热重启”重置所有变量。怎么可能保存任何状态?您是在寻找“热重载”吗?

【讨论】:

那么在物理设备上重启应用呢?这不是违背了“国家”的目的吗?我知道热重载会保持状态。 如果你想要持久化状态,你需要将你的值写入数据库或类似pub.dev/packages/shared_preferences的东西。

以上是关于StateNotifierProvider 在应用程序重新启动之间不保持状态的主要内容,如果未能解决你的问题,请参考以下文章

使用 2 个类型参数声明类型“StateNotifierProvider”,但给出了 1 个类型参数

如何设置 StateNotifierProvider 的状态

您应该将状态值放在 Riverpod 的啥位置?

如何覆盖 Riverpod StateNotifier 的状态以进行测试

在应用商店更新应用并重命名应用名称

无法在应用商店上传应用