-2

在我的应用程序中,我想在创建小部件之前初始化一些东西。我需要在App课堂上完全做到这一点,并为此目的尝试使用 FutureBuilder。但是_AppBlocProvider' 的build方法是在之前调用initInjectionContainer()的,例如。我的存储库尚未在 injectionContainer 中初始化,但提供程序中的 Blocs 正在尝试访问它的实例。这段代码有什么问题?

在此处输入图像描述

我也试过这个:

void main() {
  runApp(App());
}

class App extends StatefulWidget {
  @override
  _AppState createState() => _AppState();
}

class _AppState extends State<App> {
  Future<bool>? _myFuture;

  Future<bool> _init() async {
    ...
    await initInjectionContainer();
    await sl<AudioManager>().preloadFiles();
    return false;
  }

  ...

  @override
  void initState() {
    super.initState();
    _myFuture = _init();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: _myFuture,
      builder: (context, _) {
        return _BlocProvider(
          child: Builder(
            builder: (context) => MaterialApp(
              title: 'Flutter Demo',
              theme: ThemeData(
                primarySwatch: Colors.blue,
              ),
              home: MainMenu(),
            ),
          ),
        );
      },
    );
  }
}

不起作用。

4

1 回答 1

1

FutureBuilder不只是自动阻止或显示加载屏幕或其他任何内容。它在初始化时构建一次,然后在未来完成后再次构建。您匿名的构建器中的第二个参数对于正确处理未来状态并相应地构建至关重要。

FutureBuilder(
  future: _someFuture(),
  builder: (context, snapshot) {
    if (snapshot.connectionState != ConnectionState.done) {
      // Future not done, return a temporary loading widget
      return CircularProgressIndicator();
    }

    // Future is done, handle it properly
    return ...
  },
),

话虽如此,如果您的整个应用程序需要初始化某些东西,您可以在调用main之前调用它,runApp以便它们成为运行时加载过程的一部分,而不是强制小部件处理它:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await initInjectionContainer();
  await sl<AudioManager>().preloadFiles();

  runApp(App());
} 

虽如此,如果这些过程可能需要一段时间,最好用一个小部件来处理它们,这样你就可以向用户显示加载状态,这样他们就知道应用程序不只是在启动时冻结。

于 2021-05-12T19:03:58.963 回答