Provider 在应用程序启动时使用 SharedPreferences

Using SharedPreferences by Provider on application startup

我有 2 个启动页面,如果我在共享首选项中的“登录”下没有任何值,我想要 运行 PgStartupNew。但是我不能这样做,因为 SharedPreferences 还没有初始化。我怎样才能解决这个问题?

main.dart

        class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MultiProvider(
          providers: [
            // Provider<Future>(create: (_) => Future.value(42)),
            Provider<MySharedPreferences>(
                create: (_) => MySharedPreferences.create()),
            Provider<User>(create: (_) => User.create()),
          ],
          child: MaterialApp(
            debugShowCheckedModeBanner: false,
            theme: MyStyle.getThemeData(),
            title: 'TestApp',
            home: PgSelectStartup(),
          ),
        );
      }
    }
    
    class PgSelectStartup extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return (Provider.of<MySharedPreferences>(context).read("login") ==
                null)
            ? PgStartupNew()
            : PgStartupLogin();
      }
    }

my_shared_preferences.dart

 String? read(String key) {
    return prefs.getString(key) ?? null;
  }

错误:

════════ Exception caught by widgets library ═══════════════════════════════════
The following NoSuchMethodError was thrown building PgSelectStartup(dirty, dependencies: [_InheritedProviderScope<MySharedPreferences>]):
The method 'getString' was called on null.
Receiver: null
Tried calling: getString("login")

我尝试在构建 return 之前添加一个额外的调用 read() 方法,并尝试强制重新初始化 SharedPrefs,但它仍然无法正常工作。 class PgSelectStartup 中对 read() 的每次第一次调用都失败了,因为 prefs == null。 我该如何解决?当prefs已经初始化时如何使用“Widget build(BuildContext context)”? 我发现了一些情况如何做到这一点,但 none 在我的情况下工作,我在启动时使用 SharedPrefs,而且通过 MultiProvider

使用它

如果您想在启动时访问共享首选项,您需要在 main 中调用 runApp 之前对其进行初始化:


await MySharedPreferences.create();
// Initialize all needed asynchronous singletons.

runApp(MyApp());

或使用FutureBuilder

最后我使用 FutureBuilder 修复了它,新代码:

class PgSelectStartup extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: Provider.of<MySharedPreferences>(context).myNewInitSync(),
      builder: (context, snapshot) {
        if (snapshot.data != null) {
          return (Provider.of<MySharedPreferences>(context)
                      .read("login") ==
                  null)
              ? PgStartupNew()
              : PgStartupLogin();
        } else {
          return Column(
            children: [
              CircularProgressIndicator(),
            ],
          );
        }
      },
    );
  }
}

MySharedPreferences 中的新方法:

//old:
  static void myNewInit() async {
    prefs = await SharedPreferences.getInstance();
  }
// new:
  Future<SharedPreferences> myNewInitSync() {
    return prefs = SharedPreferences.getInstance();
  }