如何从FutureBuilder中返回不同的MaterialApp小部件

6
我需要从本地存储中获取数据,并根据该数据值确定isLogin是true还是false。如果isLogin的值为true,则返回不同的MaterialApp;如果isLogin的值为false,则返回另一个MaterialApp。
Widget build(BuildContext context) {
    return FutureBuilder(
      future: storage.ready,
      builder: (BuildContext context, snapshots) {
        if (snapshots.hasData) {
          var isLogin = storage.getItem('isLogin');
          if (snapshots.data == true) {
            return MaterialApp(
              initialRoute: '/sample',
              onGenerateRoute: RouteGenerator.generateRoute,
            );
          } else {
            return MaterialApp(
              initialRoute: '/',
              onGenerateRoute: RouteGenerator.generateRoute,
            );
          }
        }
      },
    );
  }

你找到答案了吗?我也有同样的问题。 - Andrey Solera
请检查答案。 - Atiq Ur Rehman
2个回答

2

我找到了一个解决方案,对我有用,也许能帮助未来的某个人。

以前它一直在抛出一些毫无意义的错误: 'Null check operator used on a null value. The relevant error-causing widget was MaterialApp.'

然而,我的解决方法是将应用程序转换为StatefulWidget,将future添加到initState方法中(就像在屏幕上通常做的那样),然后为每个应用程序添加键。

class DEUSApp extends StatefulWidget {
  const DEUSApp({Key key}) : super(key: key);

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

class _DEUSAppState extends State<DEUSApp> {
  Future<bool> initializeData;
  final GlobalKey _appKey = GlobalKey();
  final GlobalKey _loadingKey = GlobalKey();

  @override
  void initState() {
    super.initState();
    initializeData = context.read<SplashCubit>().initializeData();
  }

  @override
  Widget build(BuildContext ctx) {
    return BlocBuilder<SplashCubit, SplashState>(builder: (context, state) {
      // at the beginning, show a splash screen, when the data hasn't been loaded yet.
      return FutureBuilder(
        future: initializeData,
        builder: (context, snapshot) {
          if (!snapshot.hasData || !(state is SplashSuccess))
            return MaterialApp(key: _loadingKey, theme: MyStyles.theme, home: SplashScreen());

          return MaterialApp(
            key: _appKey,
            title: 'Deus Finance',
            debugShowCheckedModeBanner: false,
            theme: MyStyles.theme,
            routes: generateRoutes(context),
            initialRoute: kInitialRoute,
          );
        },
      );
    });
  }
}

我尝试使用fluro路由器。它的工作方式是不再出现红色空指针屏幕。但有一件奇怪的事情:它不再找到我的路由。它总是重定向到“/”... - AzureIP
+1 对于这个解决方案,但是如果 MyStyles.theme 是你想要返回的未来呢?占位符材料应用程序的样式需要与您实际应用程序的样式不同。 - jksevend

2

这里是我所采取的方法,我不确定它是否是最佳解决方案,但它有效。

 main() async {
  String isToNavigate = await MainAppService().getPrefValue('isToRemember');
  String typeOfUser = await MainAppService().getPrefValue('typeOfUser');
  if (isToNavigate != null) {
    if (typeOfUser == 'admin') {
      WidgetsFlutterBinding.ensureInitialized();

      runApp(AdminMyApp());
    }
    if (typeOfUser == 'client') {
      WidgetsFlutterBinding.ensureInitialized();

      runApp(MyAppClient());
    }
    if (typeOfUser == 'professional') {
      WidgetsFlutterBinding.ensureInitialized();

      runApp(MyProfessionalsApp());
    }
  } else {
    print('null is found /');
    WidgetsFlutterBinding.ensureInitialized();

    runApp(MyApp());
  }
}

很棒的想法,可以将主要功能设置成异步,并在启动应用程序之前进行配置请求! - AzureIP
在异步主函数中完成这个任务非常适合我,因为我的主题是未来,而占位符则有不同的主题,所以只需将主题作为参数传递给我的应用程序即可! - jksevend

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接