【问题标题】:Using Futurebuilder to render widgets conditionally使用 Futurebuilder 有条件地渲染小部件
【发布时间】:2020-01-25 00:49:21
【问题描述】:

我是 Flutter 和 Dart 的新手。所以我正在尝试在 Flutter 中构建一个简单的身份验证系统。当用户打开应用程序时,我想在他们登录时向他们显示LoginScreen(他们以前没有登录的地方)或HomeScreen

loadWidget,它返回一个Future 将确定是否存在持久数据,从而获取用户信息并显示主屏幕。 child 属性不允许我为其分配 Future,我不确定,但我想我必须为此使用 FutureBuilder 小部件?

第一次尝试

  Future<Widget> loadWidget() async{
    SharedPreferences prefs = await SharedPreferences.getInstance();

    // already logged in
    String phone = prefs.getString('phoneNumber');
    if (phone != null) {     
      helper.user = await checkUser(phone); // fetch user info
      return HomeScreen();
    }
    // Not logged in
    else {
      return Login();
    }
  }

对于构建功能,这不起作用

Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: loadWidget(), // This does not allow me to assign a future
    )
);
  }

第二次尝试:使用 FutureBuilder

我在这里阅读了有关 Futurebuilder how to assign future<> to widget in flutter? 的信息,它看起来像是要走的路,所以我将构建方法修改为

Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: FutureBuilder(
          future: loadWidget(),
          builder: (BuildContext context, AsyncSnapshot<Widget> widget){
            return widget;
          },
        ),
      ),
    );
  }

但这给了我以下错误:

返回类型“AsyncSnapshot”不是定义的“Widget” 通过匿名关闭。

我怎样才能做到这一点?谢谢!

【问题讨论】:

    标签: flutter dart


    【解决方案1】:

    我会将未来移到 FutureBuilder 中,然后将逻辑放入其中

      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            body: FutureBuilder(
                future: loadWidget(),
                builder: (BuildContext context, AsyncSnapshot<Widget> sharedPreference) {
                  String phone = sharedPreference.getString('phoneNumber');
                  if (phone != null) {
                    return HomeScreen();
                  }
                  // Not logged in
                  else {
                    return Login();
                  }
                }),
          ),
        );
      }
    

    【讨论】:

      【解决方案2】:

      您做得对,但问题在于 FutureBuilder 的返回对象,请参阅此代码中的 cmets:

      // *NOTE: build return Widget: Widget build...
      Widget build(BuildContext context) {
          return MaterialApp(
            home: Scaffold(
              body: FutureBuilder(
                future: loadWidget(),
                builder: (BuildContext context, AsyncSnapshot<Widget> widget){
                  // But 'widget' here is NOT a widget, it is an AsyncSnapshot object,
                  // return widget; // **is wrong**
                  // instead:
                  return widget.data;
      
                  // and better to make it like this:
                  //if (!widget.hasData) {
                  //  return Center(
                  //    child: CircularProgressIndicator(),
                  //  );
                  //}
                  //return widget.data;
                },
              ),
            ),
          );
        }
      

      那是为了修复错误。关于更简洁代码的额外建议,通过使其仅返回状态(Auth 或 Not)来保持身份验证层(loadWidget)的清洁,然后在 FutureBuilder 中使用 widget.data 捕获状态,然后根据 Auth 状态进行路由从FutureBuilder 内部。

      【讨论】:

      • 这行得通。另外,谢谢你的建议,会记住的:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-06-30
      • 2014-11-26
      • 2012-11-20
      • 1970-01-01
      • 2021-06-30
      • 2018-09-13
      • 2019-02-18
      相关资源
      最近更新 更多