如何在渲染任何东西之前等待未来?

How to wait for a future before rendering anything?

这是我的问题:

我使用 Provider 库测试 AppModel 中 currentUser 的存在,以了解我的应用程序的脚手架是否会以这种方式显示主页或登录页面:

void main() async {
  // Hive initialization ::
  WidgetsFlutterBinding.ensureInitialized();
  final document = await getApplicationDocumentsDirectory();
  Hive.init(document.path);
  runApp(
    Phoenix(
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (c) => AppModel()),
        Provider(create: (c) => UserDao()),
        ...
      ],
      child: Builder(builder: (context) {
        return MaterialApp(
          title: '_',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: AppScaffold()
        );
      }),
    );
  } // build()
}// MyApp

class AppScaffold extends StatefulWidget {

  @override
  _AppScaffoldState createState() => _AppScaffoldState();
}

class _AppScaffoldState extends State<AppScaffold> {

  @override
  initState() {
    super.initState();
    GetUserFromDB().run();
  }

  @override
  Widget build(BuildContext context) {
    // Bind to AppModel.currentUser:
    User? currentUser = context.select<AppModel, User?>((value) => value.currentUser);
    return Scaffold(
      body: currentUser != null ? HomePage(title: 'HomePage') : LoginPage(title: 'LoginPage'),
    );
  }
}

因此我的问题是,一旦用户第一次登录,当我终止并重新打开应用程序时,就会发生这种情况 ::

我的问题是我不希望用户在已经连接的情况下在进入主页之前看到登录页面,即使是短暂的...

我尝试使用 FutureBuilder 但结果相同 问题似乎是我没有足够快的 DB 用户 但是在哪里|之前怎么抓到的,明明知道之前抓不到

return MultiProvider(
      providers: [

完成...

使用启动画面来检查用户逻辑,最佳做法是将用户模型保存在内部数据库中,例如 SharedPreferences 或 hive 数据库

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await HiveConfig.initHiveDatabase();
  Firebase.initializeApp();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider<appProvider>(
            create: (context) => appProvider())
      ],
      child: const MaterialApp(
        initialRoute: '/splash',
        onGenerateRoute: app_route.Router.genarateRoute,
      ),
    );
  }
}


class Splash extends StatelessWidget {
  const Splash({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    var provider = Provider.of<appProvider>(context, listen: false);
    Future.delayed(const Duration(seconds: 4), () async {
      var hiveUserModel = await appRepositories().getHiveUserModel();

      if (hiveUserModel == null) {
        Navigator.of(context).pushNamed('/user_login');
      } else {
        provider.setHiveUser(hiveUserModel);
        Navigator.of(context).pushNamed('/home');
      }
    });

    return Scaffold(
      backgroundColor: appTheamColor,
      body: SafeArea(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Center(
                child: Column(
              children: [
                Image.asset(
                  'assets/images/app_logo.png',
                  scale: 3.4,
                ),
                const Padding(
                  padding: EdgeInsets.only(top: 12),
                  child: Text(
                    appVersion,
                    style: TextStyle(
                        color: Colors.white,
                        fontSize: 11,
                        fontWeight: FontWeight.w600),
                  ),
                ),
              ],
            ))
          ],
        ),
      ),
    );
  }
}

好吧,我终于找到了解决方法::

我移动了

Phoenix() // Allows to restart the app from wherever via Phoenix.rebirth()

从“MyApp”到“MaterialApp”。

这让我可以将 AppModel 直接实例化到 main 方法中,从而尽快得到未来的答案,即使已经连接,也不会在主页之前显示登录页面...

确实,当我开发注销功能时问题就来了,因为 Phoenix 使用提供者库执行“.dispose()”所有提供的模型|控制器|道|服务... 因此,当您在没有先终止应用程序的情况下重新连接时,Flutter 确实会启动异常,告诉您在处理模型后无法使用它...

已回答以防对其他人有用^^

PS::@harsha.kuruwita 感谢您的回答,但无法使用 splashScreen,因为我选择覆盖白色 Flutter 本机,这要归功于

flutter_native_splash: ^1.2.4

我推荐的lib ^^ 这样你:

  • 不要花时间在 2 个闪屏上
  • 并且由于无法避免原生的 >> 它允许您个性化并使其对用户来说“更酷”^^