如何在不使 main() 异步的情况下将异步对象注册到 get_it 包?

Hos*_*our 3 dependency-injection service-locator flutter

我想在 get_it 包中注册 SharedPrefrences 对象,以便从应用程序各处访问它,而不是使 main() 异步。

  1. 这是正确的方法吗?
  2. 我该怎么做?

我就是这样做的,但它抛出了异常。代码:

  appLocator.registerLazySingletonAsync<SharedPreferences>(() async {
    final sh = await SharedPreferences.getInstance();
    return sh;
  });
Run Code Online (Sandbox Code Playgroud)

例外:

未处理的异常:'package:get_it / get_it_impl.dart':断言失败:第342行第14行:'instanceFactory.isReady':您尝试访问尚未准备就绪的 SharedPreferences 实例

Dos*_*iir 6

异步主函数

将 main 函数设置为异步是一种常见的做法。等待所有异步初始化get_it有一个名为 的函数allReady()

Future main() async {

  setupServiceLocator();
  await getIt.allReady(); // wait for required async initialization

  runApp(MyApp());
}
Run Code Online (Sandbox Code Playgroud)

然后在您的设置函数中,您可以注册异步单例。

void setupServiceLocator() {
   appLocator.registerLazySingletonAsync<SharedPreferences>(() async {
    final sh = await SharedPreferences.getInstance();
    return sh;
  });
}
Run Code Online (Sandbox Code Playgroud)

未来建造者

如果您不想使主函数异步或者想要显示一些自定义加载动画,您可以简单地使用该FutureBuilder小部件。这是如何使用它的示例。例如,您可以将以下代码片段放入主应用程序小部件或启动时显示的自定义加载页面中。

FutureBuilder(
  future: getIt.allReady(),
  builder: (BuildContext context, AsyncSnapshot snapshot) {
    if (snapshot.hasData) {
      return Scaffold(
        body: Center(
          child: Text('Show this text when initialization is done.'),
        ),
      );
    } 
    else {
      // loading animation ... 
      return CircularProgressIndicator();
    }
  }
);
Run Code Online (Sandbox Code Playgroud)

FutureBuilder确保在完成之前不要使用惰性单例。为了获得更多控制,您还可以使用isReady来检查特定的单例。更多信息请参见get_it的文档。